功能组件的setState中的prevState到底是什么?
What exactly is prevState in a functional component's setState?
在从 useState
钩子获得的 setState
中返回(更改的)先前状态似乎不会改变状态。 运行 以下直接片段
function App(){
const [state, setState] = React.useState([{x: 0}])
function changeCount(){
setState(prevState => {
console.log('before', prevState[0])
const newState = [...prevState]
newState[0].x += 1 //the shallow copy newState could potentially change state
console.log('after', prevState[0])//here x gets bigger as expected
return prevState //instead of newState we return the changed prevState
})
}
//checking state shows that x remained 0
return <div className='square' onClick={changeCount}>{state[0].x}</div>
}
ReactDOM.render(<App/>, document.getElementById('root'))
.square{
width: 100px;
height: 100px;
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id='root'></div>
通过单击我们触发的正方形 setState
。在 setState
中,我们制作了先前状态的浅表副本 newState
。通过更改副本,我们在控制台确认时更改了 prevState
(可能是无意的)。返回更改后的 先前状态 形式 setState
但是不会更改状态,因为计数保持为 0。如果我们要 return newState
,行为符合预期。
重复这个,说明prevState
变大了,只是好像不再代表之前的状态了。
这是为什么? 我在 codepen...
上做了这个最小的例子
请考虑对象分配只是一个引用分配,而不是副本
obj1 = {x:42, y:99};
obj2 = obj1; // obj1 and obj2 both reference the same object
obj1.x += 1;
obj2.y += 1;
console.log(obj1.x, obj1.y);
console.log(obj2.x, obj2.y); // prints the same thing since obj1 and obj2 are the same object
在上面的示例中,obj1
被初始化为指向一个具有属性 x 和 y 的新对象。当创建 obj2=obj1
时,这不是 obj1 到 obj2 的副本,而是 obj1 和 obj2 现在引用同一个对象。
因此,当 console.log 语句打印时,它们打印相同的内容,因为它们都打印来自同一对象的 属性 值。
同理,从prevState到newState的浅拷贝时,对原始对象的附加引用也发生了。
obj = {x:42, y:99};
prevState[0] = obj; // prevState[0] is a reference to obj. prevState[0] and obj point to the same exact thing
newState = [...prevState]; // shallow copy, but newState[0] is an object reference. newState[0] and prevState[0] both point to "obj"
newState[0].x += 1; // is actually updating the original object assigned to prevState[0]
在从 useState
钩子获得的 setState
中返回(更改的)先前状态似乎不会改变状态。 运行 以下直接片段
function App(){
const [state, setState] = React.useState([{x: 0}])
function changeCount(){
setState(prevState => {
console.log('before', prevState[0])
const newState = [...prevState]
newState[0].x += 1 //the shallow copy newState could potentially change state
console.log('after', prevState[0])//here x gets bigger as expected
return prevState //instead of newState we return the changed prevState
})
}
//checking state shows that x remained 0
return <div className='square' onClick={changeCount}>{state[0].x}</div>
}
ReactDOM.render(<App/>, document.getElementById('root'))
.square{
width: 100px;
height: 100px;
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id='root'></div>
setState
。在 setState
中,我们制作了先前状态的浅表副本 newState
。通过更改副本,我们在控制台确认时更改了 prevState
(可能是无意的)。返回更改后的 先前状态 形式 setState
但是不会更改状态,因为计数保持为 0。如果我们要 return newState
,行为符合预期。
重复这个,说明prevState
变大了,只是好像不再代表之前的状态了。
这是为什么? 我在 codepen...
上做了这个最小的例子请考虑对象分配只是一个引用分配,而不是副本
obj1 = {x:42, y:99};
obj2 = obj1; // obj1 and obj2 both reference the same object
obj1.x += 1;
obj2.y += 1;
console.log(obj1.x, obj1.y);
console.log(obj2.x, obj2.y); // prints the same thing since obj1 and obj2 are the same object
在上面的示例中,obj1
被初始化为指向一个具有属性 x 和 y 的新对象。当创建 obj2=obj1
时,这不是 obj1 到 obj2 的副本,而是 obj1 和 obj2 现在引用同一个对象。
因此,当 console.log 语句打印时,它们打印相同的内容,因为它们都打印来自同一对象的 属性 值。
同理,从prevState到newState的浅拷贝时,对原始对象的附加引用也发生了。
obj = {x:42, y:99};
prevState[0] = obj; // prevState[0] is a reference to obj. prevState[0] and obj point to the same exact thing
newState = [...prevState]; // shallow copy, but newState[0] is an object reference. newState[0] and prevState[0] both point to "obj"
newState[0].x += 1; // is actually updating the original object assigned to prevState[0]