Mic*_*shi 5 reactjs react-hooks
当我使用 react 钩子更改数组中对象的属性时,该组件不会重新渲染。
我咨询了我的首席技术人员,他解释说 React 搜索“广度”而不是“深度”,这意味着 React 可以看到对象,但看不到对象属性的变化。
const [array, setArray] = useState([
{'id': 0, text: '0'},
{'id': 1, text: '1'},
{'id': 2, text: '2'}
]);
Run Code Online (Sandbox Code Playgroud)
我希望这个组件在状态改变时重新渲染,但行为就像对象数组根本没有改变一样。
如果我创建一个数组副本作为 newArray 并更改 newArray[2].text = '3' 和 setArray(newArray),react 认为数组没有改变。因此,组件不会重新加载。
作为一种解决方法,我使用
const [trigger, setTrigger] = useState(false);
setTrigger(!trigger);
Run Code Online (Sandbox Code Playgroud)
强制重新加载。然而,这是重新加载组件的一种hacky 方式,我想要一种更 React 的方式来做这件事。
先谢谢了!
您的领先技术所说的“深呼吸”是正确的。
React 仅监视“引用”更改。当您更改对象的属性时,引用是相同的。
把它想象成当你这样做时,a.value即使它被声明为常量,你仍然可以改变。
const a = {value: 'abc'}
a.value = 'xxx'
console.log(a.value) // prints 'xxx'
Run Code Online (Sandbox Code Playgroud)
但你做不到
const a = {value: 'abc'}
a = {something: 'bad'}
not allowed.
Run Code Online (Sandbox Code Playgroud)
这同样适用于对象数组(或普通的旧数组)。它是一种引用类型,因此更改数组元素的属性不会更改newArray.
newArray[2].text = '3' and setArray(newArray)
Run Code Online (Sandbox Code Playgroud)
newArray 仍然指向相同的地址空间。
因此,当您使用扩展语法 or 创建一个全新的数组时Array.from,您将创建一个全新的引用(副本),并设置一个新值,最后设置状态。
const [array, setArray] = useState([
{'id': 0, text: '0'},
{'id': 1, text: '1'},
{'id': 2, text: '2'}
]);
// ... somewhere else.
const copy = [...array, {'id': 2, ]
// or -> const copy = Array.from(array)
copy[2].text = '3'
setArray(copy)
Run Code Online (Sandbox Code Playgroud)
上面的代码创建了一个新copy的array状态。使用更新的值设置该副本将触发重新渲染。(但要注意,它会创建一个“浅拷贝”,而不是“深拷贝”)
由于您的数据结构很复杂,您不妨使用ImmerJS,它可以让您更改引用,就像您正在编写当前代码一样。
| 归档时间: |
|
| 查看次数: |
3781 次 |
| 最近记录: |