React set Hook 从组件外部的函数调用

Posted

技术标签:

【中文标题】React set Hook 从组件外部的函数调用【英文标题】:React set Hook from function call outside Component 【发布时间】:2019-07-27 02:54:49 【问题描述】:

我正在测试新的 React Hooks,我遇到了一个我无法修复的行为(也无法理解)。基本上,我有我的功能组件,并在其中设置了一个函数。该函数被传递给渲染的组件,并使用道具从最后渲染的组件中调用它。 太糟糕了,父母的钩子没有相应地更新!

我知道这似乎很难理解,但我已在此处重现错误https://codesandbox.io/s/vvwp33l7o5

如您所见,在 App 组件中,我有 onResize 函数,它应该更新 counter 钩子。这个函数被传递给ResizeObserverContainerHook 组件,当ResizeObseverContainerHook div 被调整大小时,从后者被调用。如您所见,onResize 函数中的widthheight 变量是正确的,但counter 钩子似乎没有更新!事实上,它永远等于1

我不知道,似乎我无法从组件外部更新钩子(这就像 React 有状态组件中的状态,但至少我可以像在这种情况下传递一个函数,但它没有工作:/)。

知道如何使setCounterindex.js 中的 12 处有效吗?

【问题讨论】:

【参考方案1】:

另一个答案有点混乱 - 你在做什么很好。当它说不要从内部调用钩子时,这意味着不要有条件地或从循环内调用实际的 API,例如有条件地定义useEffectuseState

您的问题源于您在 Observer.js 中传递给效果的空数组,因为它是空的,效果永远不会刷新,因此闭包是陈旧的,因此当 onResize 函数调用 setState 时,@ 987654327@ 值将始终为初始值零。

您需要让 useEffect 依赖于某些东西,这样当组件更新时,它会清除以前的效果并将新版本的 onResize 函数附加到 ResizeObserver。

我在你的沙盒里摸索了一下:https://codesandbox.io/s/x9z7k245lq?fontsize=14

它现在将计数器状态传递给 Observer 组件,并且每次计数器更改时都会运行效果。问题是我还在索引中添加了一些参考来跟踪高度/宽度,因此状态并不总是更新,否则它将无限循环。我猜你可以把它想象成shouldComponentUpdate

正确思考钩子需要一段时间。如果你想要一篇好的文章来了解钩子并避免一些关于空数组和陈旧闭包的陷阱,请查看:https://overreacted.io/making-setinterval-declarative-with-react-hooks/

【讨论】:

嗯,现在更有意义了!但是.. 是否可以不将counter 传递给ObserverObserver 应该更像是一个通用组件,它应该只在其 div 元素调整大小时运行一个函数。然后,通常,该函数会更新呈现 Observer 的组件的状态。 哦,是的,我想您完全不能将counter 向下传递,它实际上并没有做任何事情,所以您不能将第二个参数传递给useEffect - 我只是试图避免空的[]。这个实现需要注意的是它当前不会无限循环,因为onResize 函数中的宽度/高度检查。 是的,我花了一段时间才明白效果/回调中的值可能是陈旧的,尽管它们似乎直接引用了状态。我发现我链接到的那个博客对于扩展我对为什么事情没有按我预期工作的理解非常有用。

以上是关于React set Hook 从组件外部的函数调用的主要内容,如果未能解决你的问题,请参考以下文章

从react typescript组件调用外部Javascript函数

将 React Hook 传递给功能组件

React Hook父组件获取子组件的数据/函数

react hook 新特性汇总

[react] 使用Hooks要遵守哪些原则?

项目上的 React Hook