挂钩父母在孩子之前卸下

Posted

技术标签:

【中文标题】挂钩父母在孩子之前卸下【英文标题】:Hooks parent unmounted before children 【发布时间】:2020-08-13 07:58:03 【问题描述】:

几个月以来,我一直致力于做出反应。我从几天开始就开始使用 Hooks(我知道很晚了),问题是,与 React 组件相比,生命周期方法看起来在某些方面有所不同。

useEffect 钩子可以重现:

-componentDidMount();
-componentDidUpdate();
-componentWillUnMount();

但我观察到 react 的组件和函数之间的区别在于卸载函数的方式。我注意到了卸载方法,与反应的组件相比,反应的功能在子/人之前卸载父


import React,  ReactElement, useEffect, useState  from "react";
import  useLocation, useHistory  from "react-router-dom";
 
export function Child2(
  count,
  childrenUnmounted,
: 
  count: number;
  childrenUnmounted: Function;
): ReactElement 
  useEffect(() => 
    return () => 
      console.log("Unmounted");
      childrenUnmounted(count);
    ;
  , [, count]);
  return (
    <div>
      <h2>Unmouted</h2>
    </div>
  );


export function Child1( count :  count: number ): ReactElement 
  const [validation, setValidation] = useState(false);
  const usehistory = useHistory();
  const childrenUnmounted = (count: number) => 
    console.log("validation", validation, count);
    setValidation(false);
  ;

  const changeUrl = () => 
    setValidation(true);
    usehistory.push("http://localhost:3000/$count");
  ;

  return (
    <div>
      <h2>incremente</h2>
      <Child2
        count=count
        childrenUnmounted=(count: number) => childrenUnmounted(count)
      />
      <button className="button" onClick=() => changeUrl()>
        validation
      </button>
      <button
        className="button"
        onClick=() => usehistory.push(`http://localhost:3000/$count`)
      >
        nope
      </button>
    </div>
  );


export default function Parent(): ReactElement 
  const [count, setcount] = useState(-1);
  const location = useLocation();
  useEffect(() => 
    setcount(count + 1);
  , [, location]);
  return (
    <div>
      <h2>hello</h2>
      <h3>count</h3>
      <Child1 count=count />
    </div>
  );



当您单击validation 按钮时,上面的代码会发生一些烦人的事情。 Child1中的值是true,在点击的那一刻,它改变了URL来触发重新渲染Parent来改变数据(这里是计数)。

我不明白的是为什么在 Child1 中卸载 Child2 时,在 Child1 中调用的 childrenUnmounted(count)(触发相同的函数但在 Child1 中)验证等于 false,甚至点击验证?当您在验证后单击nope 时,您得到了真实...看起来 Child1 与validation 的当前状态无关(他使用以前的状态)

有人可以帮助我了解发生了什么吗? 感谢您的帮助。



解决方案:

我在验证中使用了 useRef 而不是 useState 以不依赖于重新渲染,正如 Giovanni Esposito 所说:

因为钩子是异步的,您无法获得为状态设置的最后一个值

所以 useRef 是我的解决方案

【问题讨论】:

【参考方案1】:

Ciao,我认为您的问题与何时您记录validation 值有关。我解释得更好。

您的父母关系是:父母 -> Child1 -> Child2。好的。

现在您单击 Child2 上的 validation 按钮。 validation 按钮调用 changeUrl 调用 usehistory.push("http://localhost:3000/$count"); 并且开始更改 validation(为什么要开始?因为 setValidation 是异步的)。

如果 Child2 现在卸载,可能是 validation 的值尚未由 async setValidation 设置(并且日志返回 validation 的旧值)。

好吧,在某个时候,setValidation 完成并将 validation 设置为 true。现在点击nope 按钮,validation(最后设置的值)为 true。

所以,简而言之,我认为您在日志中看到的只是因为钩子是异步的,并且您无法获得为状态设置的最后一个值(如果您以这种方式使用日志)。您必须始终记录最后设置的值的唯一方法是 useEffect 挂钩,其中包含您要登录 deps 列表的值。

【讨论】:

是的,你说得对!至少我找到了解决这个问题的方法。如果我在验证中使用 useRef 而不是 useState ,我可以直接使用该值,因为 useRef 不需要重新渲染来修改该值;)thx 很高兴听到这个消息。如果您发现此答案有用,请标记为有效。祝你有美好的一天:)

以上是关于挂钩父母在孩子之前卸下的主要内容,如果未能解决你的问题,请参考以下文章

sql查询:如何让父母没有孩子?

破坏父母和孩子的秩序

使用谓词在 Core Data 中获取父母的所有孩子

收到错误“指定的孩子已经有父母。您必须先在孩子的父母上调用 removeView()。”? [复制]

冲突的 Android 错误消息:指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

SASS - 它的父母和另一个父母的孩子的嵌套孩子