我正在尝试将挂钩与一些旧版React代码集成在一起。我的旧React代码触发了componentDidMount的回调。我想在回调中使用钩子来更新某些状态,但这似乎不起作用:该钩子被原始值卡住了。这是一个精简的,可复制的示例:
https://jsfiddle.net/0yf2xm96/16/
const Test = () => {
const [value, setValue] = React.useState(0);
return (
<div>
<Test2 onMount={() => setValue(value + 1)} />
<Test2 onMount={() => setValue(value + 1)} />
{ value /* displays 1, but I'd like to see 2 */ }
</div>
);
}
class Test2 extends React.Component {
componentDidMount() {
this.props.onMount();
}
render() { return null; }
}
ReactDOM.render(<Test />, document.querySelector("#app"))
我希望显示2,而不是1-我该怎么做?
答案 0 :(得分:2)
您可以将函数传递到SOCK_STREAM
挂钩,该函数将先前的状态值作为参数,如docs所示。
将您的onMount更改为:
useState
答案 1 :(得分:1)
Ciao,我建议您这样修改代码:
const Test = () => {
const [value, setValue] = React.useState(0);
return (
<div>
<Test2 onMount={() => setValue(value => value + 1)} />
<Test2 onMount={() => setValue(value => value + 1)} />
{ value }
</div>
);
}
说明:您知道钩子是异步的,如果仅调用setValue(value + 1)
,则不会考虑value
的先前值。如果您使用箭头功能,则该问题将得到解决。
Here您的代码已修改。
答案 2 :(得分:1)
TLDR:值是“陈旧的”。使用功能更新。
让我们首先用简单的javascript术语来思考这个问题。
Test
是一个函数。是的,它是一个组件,因此像具有特殊JSX语法的特殊功能一样被使用,但最终只是一个功能。
有了这样的理解,我们还可以理解value
虽然是useState
钩子的一部分,但它只是一个javascript变量。实际上,它的const
意味着它的值在声明后不能更改。我认为这是大多数人对useState
钩子的误解-仅仅因为它是有状态的并不意味着它可以放弃成为const
的规则。
当您调用useState
更新程序时,它将通知React需要重新渲染组件。 此重新渲染可能不会立即发生。重新渲染组件后,将再次调用函数Test
。其含义是创建了名为const
的 new value
。新的const
被分配了从useState
更新程序传递来的值。这就是使挂钩如此强大的原因。设置状态不是简单的变量分配,而是一种通过多个函数调用维护值的方法。
回到问题: 当您像在此处一样声明两个箭头函数时:
<Test2 onMount={() => setValue(value + 1)} />
<Test2 onMount={() => setValue(value + 1)} />
您现在可以希望看到这两个函数中的value
为0。即使在调用第一个函数之后,value
仍为const
,并且仍然保留值0。函数在下一个渲染周期之前调用,这意味着要调用的第二个函数成为value
失效的受害者。
使用设置状态的回调版本,称为functional updates。最终,大多数人都会弄清楚解决方案,无论他们是否理解为什么。使用更新程序表单时,始终保证传递给回调函数的状态值使用最新版本,从而消除了问题。