Reactjs 在子对象之前卸载父对象

Reactjs 在子对象之前卸载父对象,reactjs,react-hooks,Reactjs,React Hooks,几个月以来我一直在做react。我从几天开始使用钩子(我知道得很晚),事情是,与生命周期方法相比,它们在某些方面看起来是不同的 useEffect挂钩可以复制: -componentDidMount(); -componentDidUpdate(); -componentWillUnMount(); 但我观察到react的组件和函数之间的差异,这与函数的卸载方式有关。我注意到了unmount方法,与react的组件相比,react的函数在子/ren之前卸载父级 import React, {

几个月以来我一直在做react。我从几天开始使用钩子(我知道得很晚),事情是,与生命周期方法相比,它们在某些方面看起来是不同的

useEffect挂钩可以复制:

-componentDidMount();
-componentDidUpdate();
-componentWillUnMount();
但我观察到react的组件和函数之间的差异,这与函数的卸载方式有关。我注意到了unmount方法,与react的组件相比,react的函数在子/ren之前卸载父级


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>
  );
}



从“React”导入React,{ReactElement,useffect,useState};
从“react router dom”导入{useLocation,useHistory};
导出函数Child2({
计数
未安装的儿童,
}: {
计数:数字;
未安装的儿童:功能;
}):反应元件{
useffect(()=>{
return()=>{
console.log(“卸载”);
未安装的儿童(计数);
};
},[计数];
返回(
不为所动
);
}
导出函数Child1({count}:{count:number}):ReactElement{
const[validation,setValidation]=useState(false);
const usehistory=usehistory();
const childrenUnmounted=(计数:数字)=>{
日志(“验证”、验证、计数);
设置验证(假);
};
常量changeUrl=()=>{
设置验证(真);
usehistory.push(“http://localhost:3000/${count}”);
};
返回(
递增
childrenUnmounted(计数)}
/>
changeUrl()}>
验证
使用history.push(`http://localhost:3000/${count}`)}
>
不
);
}
导出默认函数父级():ReactElement{
const[count,setcount]=useState(-1);
const location=useLocation();
useffect(()=>{
设置计数(计数+1);
},[地点];
返回(
你好
{count}
);
}
当你点击
validation
按钮时,上面的代码会发生一些恼人的事情。单击时,
Child1
中的值为
true
,更改
URL
可触发父项的重新加载程序以更改数据(此处为计数)

我不明白的是,为什么在卸载Child2时,在调用Child1中的childrenUnmounted(count)(触发相同的函数,但在Child1中)时,即使单击了验证,验证也等于
false
?当你在验证后点击
nope
时,你得到了正确的答案。。。看起来孩子1不在乎验证的当前状态(他使用以前的状态)

有人能帮我了解发生了什么事吗? 谢谢你的帮助



解决方案:

我在验证中使用了useRef而不是useState,以避免重新渲染,因为Giovanni Esposito说:

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


所以useRef是我的解决方案

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

您的父母关系是:父母->子女1->子女2。嗯

现在您单击Child2上的
验证
按钮<代码>验证
按钮调用调用
changeUrl
的调用
usehistory.push(“http://localhost:3000/${count}”)开始更改
验证
(为什么会启动?因为
设置验证
是异步的)

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

嗯,在某个时刻,这个
setValidation
完成并将
validation
设置为true。现在,单击
nope
按钮,您将获得
验证的true(设置的最后一个值)


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

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