我对道具如何与钩子创建的状态进行交互有疑问。
在下面的示例中,钩子中保持的状态始终落后于道具中定义的状态。
我思考我理解为什么会这样。生命周期似乎是这样的:
- 组件渲染
-
handleclick
定义为可基于此渲染器访问范围 - 单击按钮并调用
handleclick
-
handleclick
仍然只能访问渲染中定义的范围,因此items
仍为空 -
add
被调用;父组件中的状态已更新,但是setHookItems
将使用在定义handleclick
时在props中定义的状态 -
hookItems
设置为items
,它为空
这是第一次渲染,但我认为该原理适用于所有其他渲染;单击处理程序只能访问添加新项目之前的 范围,因此,根据其作为items
的状态来设置挂钩状态。
我对这种情况如何发生的假设可能是错误的,但似乎与我所见一致。
因此,对于实际问题;如何基于某种处理程序(而不是上次渲染时的道具)基于最新道具更新处于挂钩状态的项目?
const { useState } = React;
const App = ({items,add}) => {
const [hookItems,setHookItems] = React.useState([]);
const handleclick = () => {
add(Math.floor(Math.random() * 10));
setHookItems(items);
}
return (
<div>
<p><span class="title">All Items: </span>{items.map(x => (<span>{x}</span>))}</p>
<p><span class="title">Hook Items: </span>{hookItems.map(x => (<span>{x}</span>))}</p>
<button onClick={handleclick}>Add</button>
</div>
);
}
const Root = () => {
const [items,setItems] = useState([]);
return (
<div>
<App items={items} add={item => setItems([...items,item])} />
</div>
)
}
ReactDOM.render(
<Root />,document.getElementById('app')
);
.title { display: inline-block; width: 100px; text-align: right; margin-right: 20px;}
<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="app"></div>