我尝试在我的 React hook 中使用 useEffect() 来在我的 props 更改时更新状态。但存在延迟,并且 useEffect 仅在我再次单击挂钩中的元素后才会触发。我对使用钩子相当陌生,任何帮助将不胜感激。谢谢
function ImageOrderSelect (props) {
const [clicked, setClicked] = useState(false)
const [options, setOptions] = useState(props.options)
const [current, setCurrent] = useState(props.current)
useEffect(() => {
setCurrent(props.current)
}, [props.current])
if(!clicked){
return (
<div className="image-order-select-icon" onClick={() => setClicked(!clicked)}>
<FontAwesomeIcon size="lg" icon={faCircle} />
<p>{current}</p>
</div>
)
} else if(clicked){
return (
<div className="image-order-select">
{optionsList}
</div>
)
}
}
useEffect(() => {
setTimeout(()=>{
setCurrent(props.current)
}, 1000)
}, [props.current])
您只需要在显示当前内容之前添加超时/延迟...
或者最好的方法添加回调函数
useEffect(() => {
setCurrent(() => props.current)
}, [props.current])
我不太确定您想要什么效果,但这里有一些经过清理的代码。也许这会对您有进一步帮助。
function ImageOrderSelect ({ current, options ) { // deconstruct here to save code
const [clicked, setClicked] = useState(false);
// you dont have to keep additional state since props is a state.
useEffect(() => {
setTimeout(() => {
// do something here 1 sec after current has changed
}, 1000);
}, [current]);
useEffect(() => {
setTimeout(() => {
// do something 1 sec after clicked has changed
}, 1000);
}, [clicked]);
if(!clicked){
return (
<div className="image-order-select-icon" onClick={() => setClicked(!clicked)}>
<FontAwesomeIcon size="lg" icon={faCircle} />
<p>{current}</p>
</div>
)
} else if(clicked){
return (
<div className="image-order-select">
{optionsList}
</div>
)
}
}
如果您希望在最后一次点击图像后 1 秒触发效果,则必须在每次点击时重置超时,直到超时。这是对用户交互产生任何延迟影响的常见做法:
let timeout;
useEffect(() => {
clearTimeout(timeout);
timeout = setTimeout(() => {
// do something 1 sec after a click is done
// but dont do anything if another click happened before 1sec of the previous
// click has expired
}, 1000);
}, [clicked]);
如果您能提供更详细的代码示例以及对您想要的 UI 效果更深入的解释,我绝对可以帮助您。
如果组件被用户操作(例如移动到另一个窗口)卸载。这里的超时示例仍然会执行该操作。根据具体情况,它会产生错误。以下是如何在卸载时删除计时器的示例。
const [timerReference, setTimerReference] = useState(undefined);
useEffect(() => {
setTimerReference(setTimeout(() => {
handler();
},2000));
return () => {
clearTimeout(timerReference);
}
}, []);
let optionsList = options.map((option, index) => {
return (
<div key={index} onClick={() => {
props.handleImageSort(option, props.index)
setTimeout(() => {
setClicked(!clicked)
}, .500)
}}>
<p>{option}</p>
</div>
)
})
问题是我试图同时调用 setClicked ,但由于某种原因阻止了它的调用。 setTimeout 使它可以工作,尽管并不理想。如果有人有更好的解决方案会有兴趣听听。
const timeout = useRef<NodeJS.Timeout>();
useEffect(() => {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {
"Your action here"
});
}, [your dependencies here]);