我在一个使用Redux的自定义React钩子中遇到了一个问题。这个问题与同一个钩子中函数内外的变量值不一致有关。下面是简化的代码:
import { useAppSelector } from "Redux/helpers";
import { selectAgentState } from "Redux/slices/agentSlice";
const useRemoveRoomNotif = () => {
const notifications = useAppSelector((state) => selectAgentState(state).notifications);
console.log("Outside function:", notifications);
const removeNotif = (rid: string, markNotificationsAsRead) => {
console.log("Inside function:", notifications);
const ntf = notifications.filter((notif) => notif.roomID === rid && !notif.isRead);
if (ntf.length !== 0) markNotificationsAsRead(ntf);
};
return { removeNotif };
};
export default useRemoveRoomNotif;
字符串
问题是removeNotif
函数内部的notifications值与函数外部的值不同。我假设因为它是同一个变量,所以值应该是相同的。
我尝试使用useState
,useEffect
和useRef
来确保在函数中使用正确的值:
const useRemoveRoomNotif = () => {
const notifications = useAppSelector((state) => selectAgentState(state).notifications);
const [update, setUpdate] = useState(false);
const [id, seId] = useState("");
const markAsReadRef = useRef<(notifications: INotification[]) => void>();
useEffect(() => {
if (!update) return;
const ntf = notifications.filter((notif) => notif.roomID === id && !notif.isRead);
if (ntf.length !== 0 && markAsReadRef.current) {
markAsReadRef.current(ntf);
}
setUpdate(false);
}, [notifications, markAsReadRef, id, update, setUpdate]);
const removeNotif = useCallback(
(rid: string, markNotificationsAsRead: (notifications: INotification[]) => void) => {
seId(rid);
markAsReadRef.current = markNotificationsAsRead;
setUpdate(true);
},
[notifications, seId, markAsReadRef]
);
return { removeNotif };
};
export default useRemoveRoomNotif;
型
有人能帮助我理解为什么最初的实施没有按预期工作,如果变通办法是必要的?任何见解或改进建议将不胜感激。谢谢!
1条答案
按热度按时间bakd9h0s1#
简单地说,您在
removeNotif
回调函数中遇到了一个关于所选notifications
状态值的陈旧闭包的问题。换句话说,removeNotif
在其生命周期中永远不会看到任何更新的notifications
值。你尝试的解决方法也相当复杂。我相信你可以使用React
useCallback
钩子来实现一个工作解决方案,将当前notifications
状态值重新封装在removeNotif
回调处理程序中。字符串
如果你的代码没有使用更新的
removeNotif
回调引用,即它被用作事件侦听器,那么另一种方法是在React ref中“缓存”当前notifications
值,并在removeNotif
处理程序中引用ref的当前值。范例:
型