直接修改 React 组件的状态是否可靠且一致?
Directly modifying the state of a react component works reliably and consistently?
在查看同事的 ReactJS 代码时,我注意到了它们 "modifying the state directly"。我也用这段代码试过了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {"message":""};
}
textChange(evt) {
this.state.message = evt.currentTarget.value;
this.setState({});
}
render() {
return (
<div>
<p>{this.state.message}</p>
<input type="text" onChange={evt=>this.textChange(evt)} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
</script>
</body>
</html>
方法textChange(evt)
一致且可靠地更新状态。我在互联网上的一些博客中读到我们 不应该 直接修改状态...我是不是误解了什么?
还要考虑所有这些其他修改状态的方法:
textChange1(evt) {
this.state.message = evt.currentTarget.value;
this.setState(this.state);
}
textChange2(evt) {
const state = this.state;
state.message = evt.currentTarget.value;
this.setState(state);
}
textChange3(evt) {
const state = this.state;
state.message = evt.currentTarget.value;
this.setState({});
}
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
textChange5(evt) {
let message = evt.currentTarget.value;
this.setState({message});
}
在 ReactJS 中修改状态的惯用方法是什么?
你是对的,我们不应该直接修改状态(除非它在构造函数中)。这样做可能有效,但会导致意想不到的副作用。
always create new objects and arrays when you call setState,
来源:https://daveceddia.com/why-not-modify-react-state-directly/
Do Not Modify State Directly # <--- from react docs itself
来源:https://reactjs.org/docs/state-and-lifecycle.html
在您的示例中,以下 2 种是 best/idiomatic 修改状态的方法。请注意,当您使用 {}
时,您正在初始化一个对象文字(即创建一个新对象),这就是以下两种方法正在做的事情(但当然这本身并不意味着它是正确的,因为你可以用 textChange3
).
查看
// great
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
// great
textChange5(evt) {
let message = evt.currentTarget.value; // note `let` should be `const` (style-wise) since you are not reassigning message, but otherwise this is fine!
this.setState({message});
}
用注释分解每个方法
// not good
textChange1(evt) {
this.state.message = evt.currentTarget.value; // modifying original state object
this.setState(this.state);
}
// not good
textChange2(evt) {
const state = this.state; // this is the exact same as above,
// except you aliased this.state as state.
state.message = evt.currentTarget.value;
this.setState(state);
}
// not good
textChange3(evt) {
const state = this.state;
state.message = evt.currentTarget.value; // same problem as above of modifiying state directly
this.setState({}); // you might expect the state to be set to an empty object, but it's not
// in this case it's basically a no-op because state updates are merged. see https://reactjs.org/docs/state-and-lifecycle.html
}
// great
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
// great
textChange5(evt) {
let message = evt.currentTarget.value; // note `let` should be `const` (style-wise) since you are not reassigning message, but otherwise this is fine!
this.setState({message});
}
在查看同事的 ReactJS 代码时,我注意到了它们 "modifying the state directly"。我也用这段代码试过了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props);
this.state = {"message":""};
}
textChange(evt) {
this.state.message = evt.currentTarget.value;
this.setState({});
}
render() {
return (
<div>
<p>{this.state.message}</p>
<input type="text" onChange={evt=>this.textChange(evt)} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
</script>
</body>
</html>
方法textChange(evt)
一致且可靠地更新状态。我在互联网上的一些博客中读到我们 不应该 直接修改状态...我是不是误解了什么?
还要考虑所有这些其他修改状态的方法:
textChange1(evt) {
this.state.message = evt.currentTarget.value;
this.setState(this.state);
}
textChange2(evt) {
const state = this.state;
state.message = evt.currentTarget.value;
this.setState(state);
}
textChange3(evt) {
const state = this.state;
state.message = evt.currentTarget.value;
this.setState({});
}
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
textChange5(evt) {
let message = evt.currentTarget.value;
this.setState({message});
}
在 ReactJS 中修改状态的惯用方法是什么?
你是对的,我们不应该直接修改状态(除非它在构造函数中)。这样做可能有效,但会导致意想不到的副作用。
always create new objects and arrays when you call setState,
来源:https://daveceddia.com/why-not-modify-react-state-directly/
Do Not Modify State Directly # <--- from react docs itself
来源:https://reactjs.org/docs/state-and-lifecycle.html
在您的示例中,以下 2 种是 best/idiomatic 修改状态的方法。请注意,当您使用 {}
时,您正在初始化一个对象文字(即创建一个新对象),这就是以下两种方法正在做的事情(但当然这本身并不意味着它是正确的,因为你可以用 textChange3
).
// great
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
// great
textChange5(evt) {
let message = evt.currentTarget.value; // note `let` should be `const` (style-wise) since you are not reassigning message, but otherwise this is fine!
this.setState({message});
}
用注释分解每个方法
// not good
textChange1(evt) {
this.state.message = evt.currentTarget.value; // modifying original state object
this.setState(this.state);
}
// not good
textChange2(evt) {
const state = this.state; // this is the exact same as above,
// except you aliased this.state as state.
state.message = evt.currentTarget.value;
this.setState(state);
}
// not good
textChange3(evt) {
const state = this.state;
state.message = evt.currentTarget.value; // same problem as above of modifiying state directly
this.setState({}); // you might expect the state to be set to an empty object, but it's not
// in this case it's basically a no-op because state updates are merged. see https://reactjs.org/docs/state-and-lifecycle.html
}
// great
textChange4(evt) {
this.setState({message:evt.currentTarget.value});
}
// great
textChange5(evt) {
let message = evt.currentTarget.value; // note `let` should be `const` (style-wise) since you are not reassigning message, but otherwise this is fine!
this.setState({message});
}