繁体   English   中英

React hooks:从子组件中获取当前值,无需重新渲染

[英]React hooks: get current value from child component with no constant rerender

页面上有柜台。 为了避免每秒重新渲染整个Parent组件,计数器被放置在一个单独的Child组件中。

有时需要从计数器Child获取当前时间(在此示例中通过单击按钮)。

我通过传递空的 object 作为依赖项找到了执行useEffect的解决方案。 即使它有效,我也不觉得这个解决方案是正确的。 您对如何改进此代码有什么建议吗?

父组件:

const Parent = () => {
  const [getChildValue, setGetChildValue] = useState(0);
  const [triggerChild, setTriggerChild] = useState(0); // set just to force triggering in Child

  const fooJustToTriggerChildAction = () => {
    setTriggerChild({}); // set new empty object to force useEffect in child
  };

  const handleValueFromChild = (timeFromChild) => {
    console.log('Current time from child:', timeFromChild);
  };
  
  return (
    <>
      <Child 
        handleValueFromChild={handleValueFromChild}
        triggerChild={triggerChild}
      /> 
      <Button onPress={fooJustToTriggerChildAction} >
        Click to take time
      </Button>
    </>
  );
};

子组件

const Child = ({
    triggerChild,
    handleValueFromChild,
  }) => {

  const [totalTime, setTotalTime] = useState(0);
  const totalTimeRef = useRef(totalTime); // useRef to handle totalTime inside useEffect

  const counter = () => {
    totalTimeRef.current = totalTimeRef.current + 1;
    setTotalTime(totalTimeRef.current);
    
    setTimeout(counter, 1000);
  };

  useEffect(() => {
    counter();
  }, []); // Run time counter at first render

  useEffect(() => {
    const valueForParent = totalTimeRef.current;
    handleValueFromChild(valueForParent); // use Parent's function to pass new time
  }, [triggerChild]); // Force triggering with empty object

  return (
    <>
      <div>Total time: {totalTime}</div>
    </>
  );
};

鉴于您的一组要求,我会做类似的事情,尽管有一个小的改变。

我不会传递一个空的 object(这显然可以作为 {},== {}),而是将一个 boolean 标志传递给我的孩子。 请求传回当前的计时器值,一旦传递了值,我就会将标志重置为 false。 传递值并等待父级的下一个请求。

父组件:

const Parent = () => {
  const [timerNeeded, setTimerNeeded] = useState(false);

  const fooJustToTriggerChildAction = () => {
    setTimerNeeded(true);
  };

  const handleValueFromChild = (timeFromChild) => {
    console.log('Current time from child:', timeFromChild);
    setTimerNeeded(false);
  };
  
  return (
    <>
      <Child 
        handleValueFromChild={handleValueFromChild}
        timerNeeded={timerNeeded}
      /> 
      <Button onPress={fooJustToTriggerChildAction} >
        Click to take time
      </Button>
    </>
  );
};

子组件

const Child = ({
    timerNeeded,
    handleValueFromChild,
  }) => {

  const [totalTime, setTotalTime] = useState(0);
  const totalTimeRef = useRef(totalTime); // useRef to handle totalTime inside useEffect

  const counter = () => {
    totalTimeRef.current = totalTimeRef.current + 1;
    setTotalTime(totalTimeRef.current);
    
    setTimeout(counter, 1000);
  };

  useEffect(() => {
    counter();
  }, []); // Run time counter at first render

  useEffect(() => {
    if (timerNeeded) {
      handleValueFromChild(totalTimeRef.current);
    }
}, [timerNeeded]);

  return (
    <>
      <div>Total time: {totalTime}</div>
    </>
  );
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM