tldr; 如何模拟componentDidUpdate或将keyprop与数组配合使用以强制重置组件?
componentDidUpdate
key
我正在实现一个显示计时器的组件,并在该组件达到零时执行回调。目的是让回调更新对象列表。后一个组件由新的React钩子 useState和组成useEffect。
useState
useEffect
该state包含在该定时器启动时的基准,而剩余的时间。该effect套间隔称为每秒钟更新的剩余时间,并检查是否回调应该叫。
state
effect
该组件并不是要重新安排计时器的时间,或者在间隔达到零时保持间隔不变,而是应该执行回调和空闲。为了刷新计时器,我希望将一个数组传递给该数组,key这将导致组件状态被重置,因此计时器将重新启动。不幸的是,key必须将其与字符串一起使用,因此数组的引用是否已更改均无效。
我还尝试通过传递我所关注的数组来对道具进行更改,但是状态得以维持,因此间隔未重置。
什么是观察数组中浅层变化以强制仅使用新的hooks API更新状态的首选方法?
import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; function getTimeRemaining(startedAt, delay) { const now = new Date(); const end = new Date(startedAt.getTime() + delay); return Math.max(0, end.getTime() - now.getTime()); } function RefresherTimer(props) { const [startedAt, setStartedAt] = useState(new Date()); const [timeRemaining, setTimeRemaining] = useState(getTimeRemaining(startedAt, props.delay)); useEffect(() => { if (timeRemaining <= 0) { // The component is set to idle, we do not set the interval. return; } // Set the interval to refresh the component every second. const i = setInterval(() => { const nowRemaining = getTimeRemaining(startedAt, props.delay); setTimeRemaining(nowRemaining); if (nowRemaining <= 0) { props.callback(); clearInterval(i); } }, 1000); return () => { clearInterval(i); }; }); let message = `Refreshing in ${Math.ceil(timeRemaining / 1000)}s.`; if (timeRemaining <= 0) { message = 'Refreshing now...'; } return <div>{message}</div>; } RefresherTimer.propTypes = { callback: PropTypes.func.isRequired, delay: PropTypes.number }; RefresherTimer.defaultProps = { delay: 2000 }; export default RefresherTimer;
尝试与使用key:
<RefresherTimer delay={20000} callback={props.updateListOfObjects} key={listOfObjects} />
尝试与道具变更配合使用:
<RefresherTimer delay={20000} callback={props.updateListOfObjects} somethingThatChanges={listOfObjects} />
listOfObjects指的是对象数组,其中对象本身不一定会更改,因此应与进行比较!==。通常,该值将来自Redux,该操作将updateListOfObjects导致数组重新初始化,如下所示:newListOfObjects = [...listOfObjects]。
listOfObjects
!==
Redux
updateListOfObjects
newListOfObjects = [...listOfObjects]
所述useRef创建了功能成分的“实例变量”。它充当标志来指示它是处于安装阶段还是处于更新阶段而不处于更新状态。
useRef
const mounted = useRef(); useEffect(() => { if (!mounted.current) { mounted.current = true; } else { // do componentDidUpate logic } });