React状态设置函数未更改状态。

huangapple go评论71阅读模式
英文:

React state setter function not changing the state

问题

我正在我的React项目中开发一个历史记录组件。我有history状态和一个设置器函数setHistory()。我有两个处理点击的函数:handleClick()removeHistoryItem(),它们分别在不同的按钮上调用。在这两个函数中,我都使用setHistory()函数来改变状态,但在handleClick()中它不起作用。

const removeHistoryItem = () => {
    const newHistory = history.filter(item => item.id != id)
    setHistory(newHistory)
}
    
const handleClick = () => {
    let newHistory = history
    let [selectedGame] = history.filter(item => item.id == id)
    const index = history.indexOf(selectedGame)
    
    selectedGame.isFavorite = !selectedGame.isFavorite
    newHistory.splice(index, 1, selectedGame)
    localStorage.setItem('history', JSON.stringify(newHistory))
    setHistory(newHistory)
}

这两个函数紧挨在一起,所以作用域应该不会有问题。这两个函数都能够正常执行其他操作(使用console.log()进行测试,localStorage也正常更改,splice和filter函数也正常工作)。甚至我传递给setHistory()函数的值都是正确的,只是状态没有改变。就好像setHistory()函数根本没有被调用。我没有收到任何错误消息,问题可能是什么呢?

英文:

I am working on a history component in my React project. I have the history state and a setter function setHistory() . I have two functions for handling clicks: handleClick() and removeHistoryItem(), which are called with different buttons. In both of them, I am changing the state with the setHistory() function, but it doesn't work in the handleClick() one.

const removeHistoryItem = () => {
    const newHistory = history.filter(item => item.id != id)
    setHistory(newHistory)
}
    
 const handleClick = () => {
    let newHistory = history
    let [selectedGame] = history.filter(item => item.id == id)
    const index = history.indexOf(selectedGame)
    
    selectedGame.isFavorite = !selectedGame.isFavorite
    newHistory.splice(index, 1, selectedGame)
    localStorage.setItem('history', JSON.stringify(newHistory))
    setHistory(newHistory)
}

The functions are next to each other so there shouldn't be a problem with the scope. Both functions are executing the other operations well (tested with console.log(), the localStorage is changed just fine, the splice and filter functions are working also). Even the value I am passing to the setHistory() function is correct, just the state is not changed. It's like the setHistory() function is not even called. I am not getting any errors, what could the problem be?

答案1

得分: 1

错误是由于引用相等引起的,你的 handleClick 函数中的 newHistoryhistory 都引用了 "memory" 中的同一个数组,你使用 splice 进行了突变,但它仍然是相同的对象,React 不会检测到更改,也不会触发重新渲染,仅因为旧值(history)=== 新值(newHistory)。

所以在这种情况下,你需要 "重新创建" 数组。对于 removeHistoryItem,一切都正常,因为 .filter 已经返回了新数组,因此新的引用,新的对象。

setHistory([...newHistory]);
英文:

Error is due to Reference equality, both newHistory and history in your handleClick function are referencing same array in "memory", which you mutate with splice, but it is still the same object, react will not detect the change and will not fire the rerender, just because oldValue (history) === newValue (newHistory).

So you need to "recreate" the array in this case. For removeHistoryItem all is ok due to .filter returns the new array already, so new reference, new object.

setHistory([...newHistory]);

huangapple
  • 本文由 发表于 2023年1月8日 22:01:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定