tldr; 如何模拟componentDidUpdate
或以其他方式使用key
带有数组的道具来强制重置我的组件?
我正在实现一个组件,它显示一个计时器并在它达到零时执行一个回调。目的是让回调更新对象列表。后一个组件由新的React hooks useState
和useEffect
.
state
包含对计时器启动时间和剩余时间的引用。设置每秒调用一次的effect
间隔来更新剩余时间,并检查是否应该调用回调。
该组件不打算重新安排计时器,或者在达到零时保持间隔,它应该执行回调并空闲。为了让计时器刷新,我希望将一个数组传递给key
它会导致组件的状态被重置,因此计时器将重新启动。不幸的是key
必须与字符串一起使用,因此无论我的数组的引用是否已更改都不会产生任何影响。
我还尝试通过传递我关心的数组来将更改推送到道具,但状态保持不变,因此间隔没有重置。
观察数组中的浅变化以强制仅使用新的钩子 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]
: