0

I cant seem to access Context state or component state from inside a DOM callback in a functional React component. I discovered the problem trying dispatch a state update in response to a document keypress.

Minimal Code sandbox demonstrating the problem here. Its a very basic reducer/context context.Provider object wrapping a child/useContext component to access context state.

The child implements a timer and a keypress callback. It also increments a local counter set with setState().

To test open the console and see the timer incrementing both the context and local component counter. Press any key to observe the callback referencing the initial state passed to the context.Provider component and the initial value for setState();

State updates arent accessible from within the DOM component.

Im always grateful for any advice given.Thanks

Laurence Fass
  • 1,614
  • 3
  • 21
  • 43
  • You are logging stale values, you have closure on context value when assigning the onkeypress callback. Notice the actual warning you having in your example. See https://stackoverflow.com/questions/59841800/react-useeffect-in-depth-use-of-useeffect/59841947#59841947 – Dennis Vash Apr 05 '22 at 14:49
  • Thanks for feedback I realise I am logging stale values that is the problem I am trying to fix. Is there a way to log latest values from within the callback? I know I can workaround this with refs for the component state but no idea how to make this work with context state.... – Laurence Fass Apr 05 '22 at 15:00

1 Answers1

0

Using refs works just as well for context state as it does for component state. A small feedback loop to reassign ref.current with each update of component state results in the desired effect.

See here

Heres the mod... I pulled out the timer from the initial example to simplify code.

  useEffect(() => {
    console.log("context state", JSON.stringify(context.state, null, 2));
    stateRef.current = context.state;
  }, [context.state]);

  useEffect(() => {
    document.onkeypress = function (e) {
      console.log(
        "actual value:", context.state,
        "ref value:", stateRef.current);
      context.dispatch({ type: "KEYPRESS", payload: e.key });
    };
  }, []);

Laurence Fass
  • 1,614
  • 3
  • 21
  • 43