React hooks:从子组件中获取当前值,不需要常量转发器



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

不时需要从计数器Child中获取当前时间(在本例中,通过单击按钮(。

我通过传递空对象作为依赖项找到了执行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>
</>
);
};

考虑到您的一组需求,我会做一些类似的事情,尽管只是做了一个小的更改。

我将向我的孩子传递一个布尔标志,请求传递回当前计时器值,而不是传递一个空对象(这显然是有效的,如{}!=={}(。一旦传递了值,我就会将标志重置为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>
</>
);
};

相关内容

最新更新