javi11/react-global-reducer

States get mixed with the given interface

javi11 opened this issue · 0 comments

Problem

Concurrent updates can provoque unexpected behaviour on the global state.

Solution

Change current interface

import React, {
  useCallback,
  useEffect,
  useContext,
  createContext,
  useState
} from 'react';

export function createContextState(defaultValue) {
  const Context = createContext(defaultValue);
  const handlers = [];

  function useContextState() {
    const state = useContext(Context);

    const updateState = useCallback(updateFn => {
      handlers.forEach(handler => handler(updateFn));
    }, []);

    return [state, updateState];
  }

  const Provider = ({ children }) => {
    const [value, setValue] = useState(defaultValue);
    useEffect(() => {
      handlers.push(updateFn => {
        const newValue = updateFn(value);
        setValue(newValue);
      });
      return () => {
        const index = handlers.indexOf(setValue);
        handlers.splice(index, 1);
      };
    }, [value]);
    return <Context.Provider value={value}>{children}</Context.Provider>;
  };

  return [Provider, useContextState];
}