ReactJS - Custom hook return function does not store actual data of internal state
P粉729436537
P粉729436537 2023-09-12 08:49:22
0
1
468

I have a custom hook for notification widgetsuseNotifications. This hook returns an array containing the next element (it is similar to the ant.design message api):

  • add: Function to add new notification
  • remove: Function to get the notification ID and delete the notification
  • contextHandler: JSX
  • passed to component rendering

When the user calls add, they are given an ID that can be used to delete the notification

This question is specifically about the delete function. Since I'm calling this function right after adding a new notification, the function receives a copy of the old list, so no new elements, and an error is thrown. How can I fix it so that the components use the same API?

useNotification hook How do I use it

Codesandbox (for testing, I did setTimeout and it called remove() within 3 seconds): https://codesandbox.io/s/goofy-smoke -5q7dw3?file=/src/App.js:405-440

P粉729436537
P粉729436537

reply all(1)
P粉478188786

You can make your remove function use the status updater function, which has access to the latest status value. This allows you to access the new list state before the component is re-rendered in remove().

Note: You are currently altering the original state by setting the nested object's isMounted property to false. Even if you copy the array, you should also copy the object being updated to avoid re-rendering issues.

Here are some modifications on how to access the latest value of the state and avoid state mutations:

const add = useCallback((params) => {
  const id = v4();
  const element = {...params, id, isMounted: true};
  setList(list => [...list, element]); // Add your new element while also making a copy of the current state (`list`)
  return id;
}, []);

const remove = useCallback((elementId) => {
  setList((list) =>
    list.map((elem) => elem.id === elementId 
      ? { ...elem, isMounted: false } 
      : elem
    )
  );
  setTimeout(() => {
    setList((list) => list.filter((elem) => elem.id !== elementId));
  }, 500);
}, []);

See examples below:

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template