1

I have made an example here: https://codesandbox.io/s/cocky-brattain-de5r4

I'm making a tabbed interface when switching from one to another, a component should first unregister itself (clearing some values from parent state) through the useEffect return function, and re-register itself (set some values in the parent). However, the clean up doesn't seem to work. i.e. the value does not change before the register function starts.

Look at the console log, the first time it logs an empty object, as the initial value. But when clicking on tab20, the logged value shows what it is before unregistering.

What is the problem here?

What I'm expecting to happen is:

(App load) -> console log: {} -> [register]aaa set to 1 -> (switch tab) -> [unregister]aaa set to undefined -> console log: {aaa: undefined(but it is 1)} -> [register]aaa set to 1

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
Xun Yang
  • 4,209
  • 8
  • 39
  • 68

1 Answers1

1

(App load) -> console log: {} -> [register]aaa set to 1 -> (switch tab) -> [unregister]aaa set to undefined -> console log: {aaa: undefined(but it is 1)} -> [register]aaa set to 1

Actually its:

(App load) -> console log (myVal):{} -> [register]aaa set to 1 -> (switch tab) -> update the closure within register with (myVal = {aaa:1}) -> [unregister]aaa set to undefined -> console log: {aaa: 1} (because of previous closure)

The problem is when you switching tab, the components re-renders and the register function is re-declared which is updating its closure (myVal).

To fix it (the logging result), get rid of the closure:

const register = useCallback(name => {
  setMyVal(prevState => {
    console.log(prevState);
    return { ...prevState, [name]: 1 };
  });
}, []);

Edit amazing-boyd-d6s3g

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118