[英]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.