I am encountering an issue in a custom React hook that uses Redux. The problem is related to the inconsistency of a variable’s value inside and outside a function within the same hook. Here’s the simplified code:
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;
he issue is that the notifications value inside the removeNotif
function is different from the value outside the function. I assumed that since it’s the same variable, the values should be the same.
I attempted a workaround using useState
, useEffect
, and useRef
to ensure the correct value is used inside the function:
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;
Can someone please help me understand why the initial implementation is not working as expected and if the workaround is necessary? Any insights or suggestions for improvement would be greatly appreciated. Thank you!
2
Answers
This manner, you may send the current
notifications
value straight to removeNotif, guaranteeing that it always utilizes the most recent state.Simply stated, you have an issue of a stale closure over the selected
notifications
state value in theremoveNotif
callback function. In other words,removeNotif
never sees any updatednotifications
value in its lifetime.Your attempted workaround is also quite convoluted. I believe you could achieve a working solution using just the React
useCallback
hook to re-enclose the currentnotifications
state value in theremoveNotif
callback handler.An alternative would be to "cache" the current
notifications
value in a React ref and reference the ref’s current value in theremoveNotif
callback.Example: