[英]Why is this onClick event handler firing twice in my create-react-app
有人能告诉我为什么这个“upvote” onClick 处理程序会触发两次吗? 日志表明它只运行一次,但它控制的分数增加了 2
export default class Container extends Component {
constructor(props) {
super(props);
this.state = {
jokes: [],
};
this.getNewJokes = this.getNewJokes.bind(this);
this.retrieveJokes = this.retrieveJokes.bind(this);
this.upVote = this.upVote.bind(this);
}
upVote(id) {
this.setState(state => {
//find the joke with the matching id and increase score by one
const modifiedJokes = state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
return joke;
});
console.log(modifiedJokes);
return { jokes: modifiedJokes };
});
}
render() {
return (
<div>
<h1>Container</h1>
{this.state.jokes.map(joke => (
<Joke
key={joke.id}
id={joke.id}
joke={joke.joke}
score={joke.score}
upVote={this.upVote}
downVote={this.downVote}
/>
))}
</div>
);
}
}
另一方面,如果我以这种方式重写处理程序,那么它只会触发一次
upVote(id) {
const modifiedJokes = this.state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
return joke;
});
this.setState({ jokes: modifiedJokes });
};
这不起作用,因为 React 使用合成事件,这些事件在处理完成时会被重用。 调用setState
的 function 形式将推迟评估(当setState
调用依赖于事件并且事件已丢失其值时,这可能很危险)。
所以这也应该有效:
this.setState((state,props) => ({ jokes: modifiedJokes}));
我目前无法找到我的消息来源,但我记得不久前遇到过这个问题。 我确信通过 React Docs 可以提供更深入的解释
我最好的猜测是,在第一种情况下,您还直接修改 state,当您执行 joke.score = joke.score + 1; 时
因为您直接在 state 数组变量和 Javascript 上执行此映射,所以在使用数组时,您只使用指向该数组的指针,而不是创建该数组的副本。
所以映射 function 可能需要数组的浅拷贝,这就是问题发生的地方。
您可以在使用之前使用 lodash 创建 state 数组的深层副本,这不会导致您的问题:
我发现出了什么问题。 我会发布一个答案,以防万一有人在遇到同样的问题时偶然发现这个问题。
在调试模式下,react 将运行某些功能两次,以阻止某些可能导致错误的操作。 其中一项操作是直接修改 state。 做的时候
this.setState(state => {
//find the joke with the matching id and increase score by one
const modifiedJokes = state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
return joke;
});
console.log(modifiedJokes);
return { jokes: modifiedJokes };
map function 返回一个新数组,其中每个元素都指向原始数组中的相同元素。 因此通过做
state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
我有效地直接修改了 state。 React 在调试模式下运行 setstate function 两次以清除这种操作。
所以修改嵌套在数组中的 object 的属性的正确“反应方式”是这样做
this.setState(state =>{
let modifiedJokes = state.jokes.map(joke => {
if (joke.id === id) {
return {...joke, score:joke.score+1}
}
else{ return joke}
})
return {jokes:modifiedJokes}
})
这样,当遇到具有正确 ID 的元素时,将由该特定元素制作副本,并且该副本的分数增加一,这不会影响仍在 state 中的实际元素保持不变,直到它被反应修改提交新的 state
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.