在React中卸载组件时,根据本地状态触发事件



我有一个具有某些内部状态的组件,该状态仅在某些事件上不会在整个应用程序中传播。

const FunComponent = (initialDescription, onSave) => {
const [description, setDescription] = useState('initialDescription');
const handleDescriptionSave = () => {
onSave(description);
}
return ( ... );
}

我的问题是组件可以被组件树中更高的东西卸载,在那一点上,我想强制触发onSave。太好了——我想——我可以用一个空的依赖数组写一个useEffect,它将在卸载时运行。

问题是onSave道具和description状态都是我的useEffect清理所依赖的。

如果我将它们添加到依赖数组中,它将在每次描述更改时保存之前的描述值。我不想那样。如果我不将它们添加到依赖数组中,它将在卸载时只使用初始的onSavedescription值。

const FunComponent = (initialDescription, onSave) => {
const [description, setDescription] = useState(initialDescription);
const handleDescriptionSave = () => {
onSave(description);
}
useEffect(() => {
return () => { onSave(description) };
}, [onSave, description])
return ( ... );
}

我想到的是将回调存储在ref中,并使其保持最新,并调用ref unmount:

const FunComponent = (initialDescription, onSave) => {
const [description, setDescription] = useState(initialDescription);
const handleDescriptionSave = useCallback(() => {
onSave(description);
}, [onSave, description]);
const handleDescriptionSaveRef = useRef(handleDescriptionSave);
useEffect(() => {
handleDescriptionSaveRef.current = handleDescriptionSave;
}, [onSave, description]);
useEffect(() => {
return () => { handleDescriptionSaveRef.current(); };
}, []);
return ( ... );
}

但这似乎是超级愚蠢的。

是否有一个我没有认识到的通用推荐模式?这会不会以某种方式失败?这是一个好的解决方案吗?

也许你可以直接将回调存储到ref中,而不需要useCallback():

const FunComponent = (initialDescription, onSave) => {
const [description, setDescription] = useState(initialDescription);
const handleDescriptionSaveRef = useRef();
useEffect(() => {
handleDescriptionSaveRef.current = () => onSave(description);
}, [onSave, description]);
useEffect(() => {
return () => { handleDescriptionSaveRef.current(); };
}, []);
return ( ... );
}

有趣的问题

你的方法看起来并不坏。您可以像这样使用特殊的钩子https://github.com/streamich/react-use/blob/master/src/useUnmount.ts

在我们的例子中,你可以为钩子提供两个参数:cb和args

const useUnmount = (fn: () => any, ...args): void => {
const fnRef = useRef(fn);
// update the ref each render so if it change the newest callback will be invoked
fnRef.current = () => fn(...args);
useEffectOnce(() => () => fnRef.current());
};

相关内容

  • 没有找到相关文章

最新更新