[英]Using hooks from a nested componentDidMount()
I am trying to integrate hooks with some legacy React code.我正在尝试将钩子与一些遗留的 React 代码集成。 My old react code triggers a callback from a componentDidMount.
我的旧反应代码触发了来自 componentDidMount 的回调。 I wanted to use a hook in the callback to update some state, but that doesnt seem to work: the hook gets stuck with the original value.
我想在回调中使用挂钩来更新一些 state,但这似乎不起作用:挂钩卡在原始值上。 Here's a pared down, reproducible example:
这是一个精简的、可重现的示例:
https://jsfiddle.net/0yf2xm96/16/ 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"))
I want that to display 2, not 1 - how would i go about doing that?我希望它显示 2,而不是 1 - 我将如何 go 这样做?
You can pass a function to the useState
hook that takes the previous state value as an argument, as seen in the docs .您可以将 function 传递给
useState
挂钩,该挂钩将先前的 state 值作为参数,如docs中所示。 Change your onMount to:将您的 onMount 更改为:
<Test2 onMount={() => setValue(prev=>prev + 1)} />
<Test2 onMount={() => setValue(prev=>prev + 1)} />
Ciao, I suggest you to modify your code like this: 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>
);
}
Explanation: you know hook are async and if you call just setValue(value + 1)
you are not considering the previous value of value
.解释:你知道钩子是异步的,如果你只调用
setValue(value + 1)
你没有考虑 value 的前一个value
。 Bu tif you use arrow funcition the problem will be solved.但是如果您使用箭头功能,问题将得到解决。
TLDR: Value is "stale". TLDR:价值是“陈旧的”。 Use a functional update.
使用功能更新。
Lets think about this in plain javascript terms first.让我们先用简单的 javascript 术语来考虑这个问题。
Test
is a function. Test
是 function。 Yes, its a component so it gets used like a special function with special JSX syntax, but ultimately its just a function.是的,它是一个组件,因此它被用作具有特殊 JSX 语法的特殊 function,但最终它只是一个 function。
With that understanding, we can also understand that value
, while it is part of a useState
hook, is just a javascript variable.有了这个理解,我们也可以理解
value
,虽然它是useState
钩子的一部分,但它只是一个 javascript 变量。 In fact, its a const
which means its value cannot be changed after it has been declared.实际上,它是一个
const
,这意味着它的值在声明后不能更改。 I think this is a misunderstanding that most people have about the useState
hook - just because it's stateful does not mean it can abandon the rules of being a const
.我认为这是大多数人对
useState
钩子的误解——仅仅因为它是有状态的并不意味着它可以放弃成为const
的规则。
When you call a useState
updater, it will signal React that the component needs to re-render.当你调用
useState
更新器时,它会向 React 发出组件需要重新渲染的信号。 This re-render may not happen immediately .这种重新渲染可能不会立即发生。 When the component is re-rendered, the function
Test
is called again.重新渲染组件时,再次调用 function
Test
。 The implications of this are that a new const
called value
is created.这意味着创建了一个名为
value
的新const
。 The new const
is assigned the value passed from the useState
updater.新的
const
被分配从useState
更新程序传递的值。 This is what makes the hook so powerful.这就是钩子如此强大的原因。 Setting state is not a simple variable assignment, it is a way to maintain values through multiple function calls.
设置 state 不是简单的变量赋值,它是一种通过多次 function 调用来维护值的方法。
Back to the issue: When you declare two arrow functions like you did here:回到问题:当你像这里一样声明两个箭头函数时:
<Test2 onMount={() => setValue(value + 1)} />
<Test2 onMount={() => setValue(value + 1)} />
You can hopefully now see that value
in both of these functions is 0. Even after the first function is called, value
is a const
and still retains the value 0. Both functions get called before the next render cycle, which means the second one to be called is victim to value
going stale.您现在可以希望看到这两个函数中的
value
都是 0。即使在第一个 function 被调用之后, value
也是一个const
并且仍然保留值 0。这两个函数在下一个渲染周期之前被调用,这意味着第二个被称为是value
过时的受害者。
Use the callback version of setting state referred to as functional updates .使用回调版本设置 state 称为功能更新。 Most people eventually figure out the solution whether they understand why or not.
大多数人最终都会找到解决方案,无论他们是否理解原因。 When using the updater form, the value of state passed into the callback function is always guaranteed to use the most recent version, thereby removing the issue.
使用更新程序表单时,传递给回调 function 的 state 的值始终保证使用最新版本,从而消除了该问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.