在哪些位置可以修改抬起状态?

问题描述 投票:0回答:1

在 React 中,提升状态并将该状态从父级传递给子级是很常见的,可以选择与回调函数一起使用,允许子级向父级发出状态应该更改的信号。

我似乎在 React 官方文档中找不到允许子组件调用该回调函数的地方。

在下面的伪代码中,我标记了孩子可以调用回调的 5 个不同位置。我正在尝试查找一些(官方)文档或参考资料,了解哪些位置是允许的。

function Parent({}){
  const [isActive, setIsActive] = useState(false);

  return (
    <>
      <Foo/>
      <Child active={isActive} onChange={setIsActive}/>
    </>
  );
}

function Child({active,onChange}){
  //Location 1: in the render code
  onChange(old => !old);

  useEffect(() => {
    //Location 2: in a useEffect
    onChange(old => !old);

    //Location 3: on complete of some async operation in the useEffect
    asyncOperationLikeFetch().then( () => onChange(old => !old));
  }, [])

  return (
    <p>{active}</p>
    <button onClick={() => {
      //Location 4: in an event handler
      onChange(old => !old)

      //Location 5: on complete of some async operation in the event handler
      asyncOperationLikeFetch().then( () => onChange(old => !old));
    }}>Toggle</>
  )
}

我找到了官方文档:

此外,您只能像这样更新当前渲染组件的状态。渲染时调用其他组件的set函数是错误的

  • 位置 4:在事件处理程序中。 React 文档中的一堆示例(例如 this )就是这样做的,所以应该允许这样做。

我还找到了一些非官方文档(但我希望能提供指向官方文档的指针):

到目前为止我什么也没找到:

  • 位置 3:在 useEffect 中完成一些异步操作
  • 位置 5:事件处理程序中完成某些异步操作时

任何人都可以告诉我在哪些位置我可以(不)调用从父级收到的回调?

reactjs react-state
1个回答
0
投票

看来你的理解是正确的。

情况 (3) 与情况 (2) 相同,在

useEffect
钩子回调中排队状态更新,类似情况 (5) 与情况 (4) 相同(以及情况 (2) 和 (3)真的!)在回调函数中排队状态更新。

基本上你只是想避免无意的副作用,例如情况(1),其中函数被无条件调用,而函数组件主体被React调用。 React 组件被视为纯函数。

情况 (2)、(3)、(4) 和 (5) 都被视为 有意的 副作用,无论是在

useEffect
钩子回调中调用,还是在某些异步调用的 DOM 事件处理程序中调用,就像按钮单击处理程序一样。

您可以深入研究旧版 React 文档,以深入了解并欣赏 React 组件生命周期。在那里,您将找到有关旧的基于类的组件生命周期的文档以及有关何时可以应用 React 状态更新的一些详细信息。

举个例子:

  • componentDidMount
    与在初始渲染周期调用
    useEffect
    准同义

    组件DidMount()

    componentDidMount()
    

    componentDidMount()
    在组件被调用后立即调用 已安装(插入树中)。需要DOM的初始化 节点应该放在这里。如果您需要从远程端点加载数据, 这是实例化网络请求的好地方。

    此方法是设置任何订阅的好地方。如果你这样做 那,别忘了在

    componentWillUnmount()
    取消订阅。

    可以立即在componentDidMount()

    中调用setState()。它
    会触发额外的渲染,但会在浏览器之前发生
    更新屏幕。这保证了即使 
    render()
    在这种情况下将被调用两次,用户将看不到中间内容
    状态。请谨慎使用此模式,因为它通常会导致
    性能问题。在大多数情况下,您应该能够分配
    初始状态改为 
    constructor()
    。然而,它可以是
    当您需要测量时,对于模态和工具提示等情况是必需的
    渲染某些内容之前的 DOM 节点,具体取决于其大小或
    位置。

  • componentWillUmount

    与useEffect钩子回调清理函数准同义
    

    组件WillUnmount()

    componentWillUnmount()

    componentWillUnmount()

     在组件被调用之前立即调用
    卸下并毁坏。在此方法中执行任何必要的清理,
    例如使计时器失效、取消网络请求或清理
    增加在 
    componentDidMount()
    中创建的所有订阅。

    不应该在componentWillUnmount()中调用setState()

    ,因为
    该组件永远不会被重新渲染。一旦组件实例被
    卸载后,将永远不会再次安装。

另请注意,您可以

始终将来自其他 DOM 事件回调的状态更新排入队列。

© www.soinside.com 2019 - 2024. All rights reserved.