Skip to content

Commit 44f6c7c

Browse files
potetojorge-cab
authored andcommitted
[compiler] new tests for props derived
Adds some new test cases for ValidateNoDerivedComputationsInEffects.
1 parent 3958d5d commit 44f6c7c

16 files changed

+659
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validateNoDerivedComputationsInEffects
6+
import {useEffect, useState} from 'react';
7+
8+
function Component({initialName}) {
9+
const [name, setName] = useState('');
10+
11+
useEffect(() => {
12+
setName(initialName);
13+
}, []);
14+
15+
return (
16+
<div>
17+
<input value={name} onChange={e => setName(e.target.value)} />
18+
</div>
19+
);
20+
}
21+
22+
export const FIXTURE_ENTRYPOINT = {
23+
fn: Component,
24+
params: [{initialName: 'John'}],
25+
};
26+
27+
```
28+
29+
## Code
30+
31+
```javascript
32+
import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
33+
import { useEffect, useState } from "react";
34+
35+
function Component(t0) {
36+
const $ = _c(6);
37+
const { initialName } = t0;
38+
const [name, setName] = useState("");
39+
let t1;
40+
if ($[0] !== initialName) {
41+
t1 = () => {
42+
setName(initialName);
43+
};
44+
$[0] = initialName;
45+
$[1] = t1;
46+
} else {
47+
t1 = $[1];
48+
}
49+
let t2;
50+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
51+
t2 = [];
52+
$[2] = t2;
53+
} else {
54+
t2 = $[2];
55+
}
56+
useEffect(t1, t2);
57+
let t3;
58+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
59+
t3 = (e) => setName(e.target.value);
60+
$[3] = t3;
61+
} else {
62+
t3 = $[3];
63+
}
64+
let t4;
65+
if ($[4] !== name) {
66+
t4 = (
67+
<div>
68+
<input value={name} onChange={t3} />
69+
</div>
70+
);
71+
$[4] = name;
72+
$[5] = t4;
73+
} else {
74+
t4 = $[5];
75+
}
76+
return t4;
77+
}
78+
79+
export const FIXTURE_ENTRYPOINT = {
80+
fn: Component,
81+
params: [{ initialName: "John" }],
82+
};
83+
84+
```
85+
86+
### Eval output
87+
(kind: ok) <div><input value="John"></div>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// @validateNoDerivedComputationsInEffects
2+
import {useEffect, useState} from 'react';
3+
4+
function Component({initialName}) {
5+
const [name, setName] = useState('');
6+
7+
useEffect(() => {
8+
setName(initialName);
9+
}, []);
10+
11+
return (
12+
<div>
13+
<input value={name} onChange={e => setName(e.target.value)} />
14+
</div>
15+
);
16+
}
17+
18+
export const FIXTURE_ENTRYPOINT = {
19+
fn: Component,
20+
params: [{initialName: 'John'}],
21+
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validateNoDerivedComputationsInEffects
6+
import {useEffect, useState} from 'react';
7+
8+
function Component({value, enabled}) {
9+
const [localValue, setLocalValue] = useState('');
10+
11+
useEffect(() => {
12+
if (enabled) {
13+
setLocalValue(value);
14+
} else {
15+
setLocalValue('disabled');
16+
}
17+
}, [value, enabled]);
18+
19+
return <div>{localValue}</div>;
20+
}
21+
22+
export const FIXTURE_ENTRYPOINT = {
23+
fn: Component,
24+
params: [{value: 'test', enabled: true}],
25+
};
26+
27+
```
28+
29+
## Code
30+
31+
```javascript
32+
import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
33+
import { useEffect, useState } from "react";
34+
35+
function Component(t0) {
36+
const $ = _c(6);
37+
const { value, enabled } = t0;
38+
const [localValue, setLocalValue] = useState("");
39+
let t1;
40+
let t2;
41+
if ($[0] !== enabled || $[1] !== value) {
42+
t1 = () => {
43+
if (enabled) {
44+
setLocalValue(value);
45+
} else {
46+
setLocalValue("disabled");
47+
}
48+
};
49+
50+
t2 = [value, enabled];
51+
$[0] = enabled;
52+
$[1] = value;
53+
$[2] = t1;
54+
$[3] = t2;
55+
} else {
56+
t1 = $[2];
57+
t2 = $[3];
58+
}
59+
useEffect(t1, t2);
60+
let t3;
61+
if ($[4] !== localValue) {
62+
t3 = <div>{localValue}</div>;
63+
$[4] = localValue;
64+
$[5] = t3;
65+
} else {
66+
t3 = $[5];
67+
}
68+
return t3;
69+
}
70+
71+
export const FIXTURE_ENTRYPOINT = {
72+
fn: Component,
73+
params: [{ value: "test", enabled: true }],
74+
};
75+
76+
```
77+
78+
### Eval output
79+
(kind: ok) <div>test</div>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// @validateNoDerivedComputationsInEffects
2+
import {useEffect, useState} from 'react';
3+
4+
function Component({value, enabled}) {
5+
const [localValue, setLocalValue] = useState('');
6+
7+
useEffect(() => {
8+
if (enabled) {
9+
setLocalValue(value);
10+
} else {
11+
setLocalValue('disabled');
12+
}
13+
}, [value, enabled]);
14+
15+
return <div>{localValue}</div>;
16+
}
17+
18+
export const FIXTURE_ENTRYPOINT = {
19+
fn: Component,
20+
params: [{value: 'test', enabled: true}],
21+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validateNoDerivedComputationsInEffects
6+
import {useEffect, useState} from 'react';
7+
8+
function Component({value}) {
9+
const [localValue, setLocalValue] = useState('');
10+
11+
useEffect(() => {
12+
console.log('Value changed:', value);
13+
setLocalValue(value);
14+
document.title = `Value: ${value}`;
15+
}, [value]);
16+
17+
return <div>{localValue}</div>;
18+
}
19+
20+
export const FIXTURE_ENTRYPOINT = {
21+
fn: Component,
22+
params: [{value: 'test'}],
23+
};
24+
25+
```
26+
27+
## Code
28+
29+
```javascript
30+
import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
31+
import { useEffect, useState } from "react";
32+
33+
function Component(t0) {
34+
const $ = _c(5);
35+
const { value } = t0;
36+
const [localValue, setLocalValue] = useState("");
37+
let t1;
38+
let t2;
39+
if ($[0] !== value) {
40+
t1 = () => {
41+
console.log("Value changed:", value);
42+
setLocalValue(value);
43+
document.title = `Value: ${value}`;
44+
};
45+
t2 = [value];
46+
$[0] = value;
47+
$[1] = t1;
48+
$[2] = t2;
49+
} else {
50+
t1 = $[1];
51+
t2 = $[2];
52+
}
53+
useEffect(t1, t2);
54+
let t3;
55+
if ($[3] !== localValue) {
56+
t3 = <div>{localValue}</div>;
57+
$[3] = localValue;
58+
$[4] = t3;
59+
} else {
60+
t3 = $[4];
61+
}
62+
return t3;
63+
}
64+
65+
export const FIXTURE_ENTRYPOINT = {
66+
fn: Component,
67+
params: [{ value: "test" }],
68+
};
69+
70+
```
71+
72+
### Eval output
73+
(kind: ok) <div>test</div>
74+
logs: ['Value changed:','test']
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @validateNoDerivedComputationsInEffects
2+
import {useEffect, useState} from 'react';
3+
4+
function Component({value}) {
5+
const [localValue, setLocalValue] = useState('');
6+
7+
useEffect(() => {
8+
console.log('Value changed:', value);
9+
setLocalValue(value);
10+
document.title = `Value: ${value}`;
11+
}, [value]);
12+
13+
return <div>{localValue}</div>;
14+
}
15+
16+
export const FIXTURE_ENTRYPOINT = {
17+
fn: Component,
18+
params: [{value: 'test'}],
19+
};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
## Input
3+
4+
```javascript
5+
// @validateNoDerivedComputationsInEffects
6+
import {useEffect, useState} from 'react';
7+
8+
function Component({prefix}) {
9+
const [name, setName] = useState('');
10+
const [displayName, setDisplayName] = useState('');
11+
12+
useEffect(() => {
13+
setDisplayName(prefix + name);
14+
}, [prefix, name]);
15+
16+
return (
17+
<div>
18+
<input value={name} onChange={e => setName(e.target.value)} />
19+
<div>{displayName}</div>
20+
</div>
21+
);
22+
}
23+
24+
export const FIXTURE_ENTRYPOINT = {
25+
fn: Component,
26+
params: [{prefix: 'Hello, '}],
27+
};
28+
29+
```
30+
31+
32+
## Error
33+
34+
```
35+
Found 1 error:
36+
37+
Error: Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)
38+
39+
error.derived-state-from-mixed-deps-no-error.ts:9:4
40+
7 |
41+
8 | useEffect(() => {
42+
> 9 | setDisplayName(prefix + name);
43+
| ^^^^^^^^^^^^^^ Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)
44+
10 | }, [prefix, name]);
45+
11 |
46+
12 | return (
47+
```
48+
49+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// @validateNoDerivedComputationsInEffects
2+
import {useEffect, useState} from 'react';
3+
4+
function Component({prefix}) {
5+
const [name, setName] = useState('');
6+
const [displayName, setDisplayName] = useState('');
7+
8+
useEffect(() => {
9+
setDisplayName(prefix + name);
10+
}, [prefix, name]);
11+
12+
return (
13+
<div>
14+
<input value={name} onChange={e => setName(e.target.value)} />
15+
<div>{displayName}</div>
16+
</div>
17+
);
18+
}
19+
20+
export const FIXTURE_ENTRYPOINT = {
21+
fn: Component,
22+
params: [{prefix: 'Hello, '}],
23+
};

0 commit comments

Comments
 (0)