mweststrate / use-st8

Single-function alternative for React.useState
MIT License
234 stars 7 forks source link

Persist the setter reference within re-renders (same as use-state setter) #25

Open realamirhe opened 8 months ago

realamirhe commented 8 months ago
function useSt8<V>(initialValue: (() => V) | V): St8<V> {
  const state = useRef(initialValue);
  const reRender = useReducer((s) => s + 1, 0)[1];

  return useMemo(() => {
    if (typeof state.current === 'function') {
      state.current = state.current();
    }

    return function st8() {
      if (!arguments.length) return state.current;

      const [value] = arguments;
      state.current =
        typeof value === 'function' ? value(state.current) : value;
      reRender();
    };
  }, []) as St8<V>;
}

Looking react doc as a reference, here are some things which could be interpreted as spec for set-state. (I know this function must not be an exact replacement for useState, but making it more similar with no cost, make it considerable)

useState returns an array with exactly two values:

realamirhe commented 8 months ago
function useSt8<V>(initialValue: (() => V) | V): St8<V> {
  const state = useRef(initialValue);
  const reRender = useReducer((s) => s + 1, 0)[1];

  return useMemo(() => {
    if (typeof state.current === "function") {
      state.current = state.current();
    }

    return function st8() {
      if (!arguments.length) return state.current;

      const [value] = arguments;
      let next = typeof value === "function" ? value(state.current) : value;
      if (!Object.is(next, current.state)) {
        state.current = next;
        reRender();
      }
    };
  }, []) as St8<V>;
}