React hooks 状态变量在重新渲染后不更新
React hooks state variable not updating after rerender
在下面的示例中,我有一个要更新的元素(水果)数组,并使用更新后的数组执行其他操作(在本例中保存更新后的列表)。我的理解是重新渲染状态将更新......但它不在这里......或者状态更新和我的行动之间存在延迟。
在 addFruit
函数中,我可以看到立即添加了 'Peach',但 saveFruits
函数的控制台仍然显示状态 fruit
保持不变。我怎样才能让这个更新立即使用。 (而且我知道在这种情况下我可以将 newFruits
变量传递给 saveFruits
进行更新,但我也需要 fruits
为其他地方进行更新)。
请原谅我,因为这是我关于反应异步状态的第 100 万个问题,但有些东西还没有让我点击。
const { useState } = React;
function ParentComp() {
const[fruits, setFruits] = useState(['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi'])
const addFruit = () => {
let newFruits = Object.assign([], fruits)
newFruits.push('Peach')
setFruits(newFruits)
saveFruits()
}
const saveFruits = () => {
console.log('API req to save fruits.', fruits)
}
return (
<div>
{ fruits.map( (fruit, key) => <div key={key}>{fruit}</div> ) }
<button type="button" onClick={addFruit}>Add Peach</button>
</div>
)
}
ReactDOM.render(<ParentComp />, document.getElementById('root'))
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
您可以尝试使用 useEffect,它会在有更新时提供更新状态。
useEffect(() => {
saveFruits();
}, [fruits]);
console.log fruits
不准确,因为对 fruits
的引用仍然指的是调用 setFruits
之前的 fruits
。
如果我们console.lognewFruits
有变化的话,会更准确。
编辑:useEffect
可能比@Atul 建议的更好。
在旧的 React 类 中可视化这是如何完成的有时会有所帮助。在旧的 React 类 中相当于这个(在某种程度上实际上不是但足以说明这一点)(阅读更多:https://reactjs.org/docs/hooks-state.html)
class ParentComp extends React.Component {
constructor() {
super();
this.state = {
fruits: ['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi']
};
}
addFruit = () => {
let newFruits = Object.assign([], this.state.fruits);
newFruits.push('Peach')
this.setFruits(newFruits)
this.saveFruits();
}
setFruits = (fruits) => {
this.setState({
fruits
});
}
saveFruits = () => {
console.log(this.state.fruits);
}
render() {
return (
<div>
{this.state.fruits.map((fruit, key) => {
return (<div key={key}>{fruit}</div>) })}
<button type="button" onClick={this.addFruit}>Add Peach</button>
</div>
);
}
}
ReactDOM.render(<ParentComp /> , document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我们在上面遇到了同样的问题,但它可能更清楚一些。 fruits
的 setState 确实被调用,但 console.log 发生在 state/render 更改发生之前,因此 this.state.fruits
仍然指的是之前的状态。
我强烈建议阅读 React hooks: not magic, just arrays 以更好地了解 hooks 幕后发生的事情。它有助于解释很多。
在下面的示例中,我有一个要更新的元素(水果)数组,并使用更新后的数组执行其他操作(在本例中保存更新后的列表)。我的理解是重新渲染状态将更新......但它不在这里......或者状态更新和我的行动之间存在延迟。
在 addFruit
函数中,我可以看到立即添加了 'Peach',但 saveFruits
函数的控制台仍然显示状态 fruit
保持不变。我怎样才能让这个更新立即使用。 (而且我知道在这种情况下我可以将 newFruits
变量传递给 saveFruits
进行更新,但我也需要 fruits
为其他地方进行更新)。
请原谅我,因为这是我关于反应异步状态的第 100 万个问题,但有些东西还没有让我点击。
const { useState } = React;
function ParentComp() {
const[fruits, setFruits] = useState(['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi'])
const addFruit = () => {
let newFruits = Object.assign([], fruits)
newFruits.push('Peach')
setFruits(newFruits)
saveFruits()
}
const saveFruits = () => {
console.log('API req to save fruits.', fruits)
}
return (
<div>
{ fruits.map( (fruit, key) => <div key={key}>{fruit}</div> ) }
<button type="button" onClick={addFruit}>Add Peach</button>
</div>
)
}
ReactDOM.render(<ParentComp />, document.getElementById('root'))
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
您可以尝试使用 useEffect,它会在有更新时提供更新状态。
useEffect(() => {
saveFruits();
}, [fruits]);
console.log fruits
不准确,因为对 fruits
的引用仍然指的是调用 setFruits
之前的 fruits
。
如果我们console.lognewFruits
有变化的话,会更准确。
编辑:useEffect
可能比@Atul 建议的更好。
在旧的 React 类 中可视化这是如何完成的有时会有所帮助。在旧的 React 类 中相当于这个(在某种程度上实际上不是但足以说明这一点)(阅读更多:https://reactjs.org/docs/hooks-state.html)
class ParentComp extends React.Component {
constructor() {
super();
this.state = {
fruits: ['Apple', 'Orange', 'Banana', 'Pomegranate', 'Kiwi']
};
}
addFruit = () => {
let newFruits = Object.assign([], this.state.fruits);
newFruits.push('Peach')
this.setFruits(newFruits)
this.saveFruits();
}
setFruits = (fruits) => {
this.setState({
fruits
});
}
saveFruits = () => {
console.log(this.state.fruits);
}
render() {
return (
<div>
{this.state.fruits.map((fruit, key) => {
return (<div key={key}>{fruit}</div>) })}
<button type="button" onClick={this.addFruit}>Add Peach</button>
</div>
);
}
}
ReactDOM.render(<ParentComp /> , document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我们在上面遇到了同样的问题,但它可能更清楚一些。 fruits
的 setState 确实被调用,但 console.log 发生在 state/render 更改发生之前,因此 this.state.fruits
仍然指的是之前的状态。
我强烈建议阅读 React hooks: not magic, just arrays 以更好地了解 hooks 幕后发生的事情。它有助于解释很多。