mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir] Improve error message for mutating state
This commit is contained in:
@@ -261,6 +261,7 @@ const BUILTIN_HOOKS: Array<[string, BuiltInType]> = [
|
||||
calleeEffect: Effect.Read,
|
||||
hookKind: "useState",
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
returnValueReason: ValueReason.State,
|
||||
}),
|
||||
],
|
||||
[
|
||||
|
||||
@@ -1122,6 +1122,11 @@ export enum ValueReason {
|
||||
*/
|
||||
Context = "context",
|
||||
|
||||
/**
|
||||
* A value returned from `useState`
|
||||
*/
|
||||
State = "state",
|
||||
|
||||
/**
|
||||
* Props of a component or arguments of a hook.
|
||||
*/
|
||||
|
||||
@@ -1768,6 +1768,8 @@ function getWriteErrorReason(abstractValue: AbstractValue): string {
|
||||
return "Mutating a value returned from a function that should not be mutated.";
|
||||
} else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {
|
||||
return "Mutating props or hook arguments is not allowed. Consider using a local variable instead.";
|
||||
} else if (abstractValue.reason.has(ValueReason.State)) {
|
||||
return "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead.";
|
||||
} else {
|
||||
return "This mutates a variable that React considers immutable.";
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ function Component(props) {
|
||||
3 | const onChange = (e) => {
|
||||
4 | // INVALID! should use copy-on-write and pass the new value
|
||||
> 5 | x.value = e.target.value;
|
||||
| ^^^^^^^ [ReactForget] InvalidReact: Mutating a value returned from a function that should not be mutated. (5:5)
|
||||
| ^^^^^^^ [ReactForget] InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. (5:5)
|
||||
6 | setX(x);
|
||||
7 | };
|
||||
8 | return <input value={x.value} onChange={onChange} />;
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { useState } from "react";
|
||||
|
||||
function Foo() {
|
||||
const [state, setState] = useState({ foo: { bar: 3 } });
|
||||
const foo = state.foo;
|
||||
foo.bar = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
4 | const [state, setState] = useState({ foo: { bar: 3 } });
|
||||
5 | const foo = state.foo;
|
||||
> 6 | foo.bar = 1;
|
||||
| ^^^ [ReactForget] InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. (6:6)
|
||||
7 | return state;
|
||||
8 | }
|
||||
9 |
|
||||
```
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { useState } from "react";
|
||||
|
||||
function Foo() {
|
||||
const [state, setState] = useState({ foo: { bar: 3 } });
|
||||
const foo = state.foo;
|
||||
foo.bar = 1;
|
||||
return state;
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { useState } from "react";
|
||||
|
||||
function Foo() {
|
||||
let [state, setState] = useState({});
|
||||
state.foo = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
3 | function Foo() {
|
||||
4 | let [state, setState] = useState({});
|
||||
> 5 | state.foo = 1;
|
||||
| ^^^^^ [ReactForget] InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. (5:5)
|
||||
6 | return state;
|
||||
7 | }
|
||||
8 |
|
||||
```
|
||||
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { useState } from "react";
|
||||
|
||||
function Foo() {
|
||||
let [state, setState] = useState({});
|
||||
state.foo = 1;
|
||||
return state;
|
||||
}
|
||||
Reference in New Issue
Block a user