Skip to content

Commit e4be4f5

Browse files
committed
[Compiler] Don't throw calculate in render when there is a prop function call in effects
1 parent ea16289 commit e4be4f5

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,19 @@ function validateEffect(
307307
sourceIds: argMetadata.sourcesIds,
308308
});
309309
}
310+
} else if (instr.value.kind === 'CallExpression') {
311+
const calleeMetadata = derivationCache.get(
312+
instr.value.callee.identifier.id,
313+
);
314+
315+
if (
316+
calleeMetadata !== undefined &&
317+
(calleeMetadata.typeOfValue === 'fromProps' ||
318+
calleeMetadata.typeOfValue === 'fromPropsAndState')
319+
) {
320+
// If the callee is a prop we can't confidently say that it should be derived in render
321+
return;
322+
}
310323
}
311324
}
312325
seenBlocks.add(block.id);
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validateNoDerivedComputationsInEffects
6+
import {useEffect, useState} from 'react';
7+
8+
function Component({propValue, onChange}) {
9+
const [value, setValue] = useState(null);
10+
useEffect(() => {
11+
setValue(propValue);
12+
onChange();
13+
}, [propValue]);
14+
15+
return <div>{value}</div>;
16+
}
17+
18+
export const FIXTURE_ENTRYPOINT = {
19+
fn: Component,
20+
params: [{propValue: 'test', onChange: () => {}}],
21+
};
22+
23+
```
24+
25+
## Code
26+
27+
```javascript
28+
import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
29+
import { useEffect, useState } from "react";
30+
31+
function Component(t0) {
32+
const $ = _c(7);
33+
const { propValue, onChange } = t0;
34+
const [value, setValue] = useState(null);
35+
let t1;
36+
if ($[0] !== onChange || $[1] !== propValue) {
37+
t1 = () => {
38+
setValue(propValue);
39+
onChange();
40+
};
41+
$[0] = onChange;
42+
$[1] = propValue;
43+
$[2] = t1;
44+
} else {
45+
t1 = $[2];
46+
}
47+
let t2;
48+
if ($[3] !== propValue) {
49+
t2 = [propValue];
50+
$[3] = propValue;
51+
$[4] = t2;
52+
} else {
53+
t2 = $[4];
54+
}
55+
useEffect(t1, t2);
56+
let t3;
57+
if ($[5] !== value) {
58+
t3 = <div>{value}</div>;
59+
$[5] = value;
60+
$[6] = t3;
61+
} else {
62+
t3 = $[6];
63+
}
64+
return t3;
65+
}
66+
67+
export const FIXTURE_ENTRYPOINT = {
68+
fn: Component,
69+
params: [{ propValue: "test", onChange: () => {} }],
70+
};
71+
72+
```
73+
74+
### Eval output
75+
(kind: ok) <div>test</div>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @validateNoDerivedComputationsInEffects
2+
import {useEffect, useState} from 'react';
3+
4+
function Component({propValue, onChange}) {
5+
const [value, setValue] = useState(null);
6+
useEffect(() => {
7+
setValue(propValue);
8+
onChange();
9+
}, [propValue]);
10+
11+
return <div>{value}</div>;
12+
}
13+
14+
export const FIXTURE_ENTRYPOINT = {
15+
fn: Component,
16+
params: [{propValue: 'test', onChange: () => {}}],
17+
};

0 commit comments

Comments
 (0)