我有一些简单的代码:
class App extends React.Component {
state = {
letters: ["a", "b", "c"]
};
addLetter = () => {
const { letters } = this.state;
letters.push("d");
this.setState({ letters });
};
render() {
return (
<div>
<button onClick={this.addLetter}>Click to add a letter</button>
<h1>letters: {this.state.letters}</h1>
</div>
);
}
}
render(<App />, document.getElementById("root"));
工作示例here。
单击按钮时,字母'd'
应添加到letters
处于状态。这按预期工作。但是,当状态发生变化时,字母不会在页面上更新。
值得注意的是:
<h1>letters: {this.state.letters.reduce((a, l) => a + l, "")}</h1>
或:
<h1>letters: {this.state.letters.toString()}</h1>
按预期更新页面。
为什么会这样?
答案 0 :(得分:3)
你需要替换字母的状态(数组),而不是改变它(working example)。根据反应docs:不要直接修改状态。
当您将数组转换为字符串时,当前字符串与前一个字符串不同,因为字符串是不可变的。但是,即使您向其中添加了另一个项目,该数组也会保持相同的数组。
示例:强>
const a = [1, 2, 3];
const strA = a.toString();
a.push(4);
const strB = a.toString();
console.log(a === a); // true
console.log(strA === strB); // false
&#13;
解决方案:从旧数组中创建一个新数组。
addLetter = () => {
const { letters } = this.state;
this.setState({ letters: [...letters, 'd'] });
};
答案 1 :(得分:1)
你已经得到了答案。想进一步解释一下。
你基本上没有改变状态。而反应只能检测状态的变化。现在棘手的部分是你可能会认为你正在更新数组对象,从而改变状态,但事实并非如此。原始数组引用永远不会在状态中更改,因此不会更改。因此,要在es6中解决此问题,您可以在addLetter声明中使用...运算符。
addLetter = () => {
const { letters } = this.state;
letters.push("d");
this.setState({ letters:[...letters] });
};
...
运算符基本上克隆了原始对象,是来自es6
的简写运算符。
您也可以使用克隆方法,例如Object.assign
希望它有所帮助!
答案 2 :(得分:0)