MCPcopy Index your code
hub / github.com/streamich/react-use / useStateWithHistory

Function useStateWithHistory

src/useStateWithHistory.ts:23–134  ·  view source on GitHub ↗
(
  initialState?: IHookStateInitAction<S>,
  capacity: number = 10,
  initialHistory?: I[]
)

Source from the content-addressed store, hash-verified

21export function useStateWithHistory<S = undefined>(): UseStateHistoryReturn<S | undefined>;
22
23export function useStateWithHistory<S, I extends S>(
24 initialState?: IHookStateInitAction<S>,
25 capacity: number = 10,
26 initialHistory?: I[]
27): UseStateHistoryReturn<S> {
28 if (capacity < 1) {
29 throw new Error(`Capacity has to be greater than 1, got '${capacity}'`);
30 }
31
32 const isFirstMount = useFirstMountState();
33 const [state, innerSetState] = useState<S>(initialState as S);
34 const history = useRef<S[]>((initialHistory ?? []) as S[]);
35 const historyPosition = useRef(0);
36
37 // do the states manipulation only on first mount, no sense to load re-renders with useless calculations
38 if (isFirstMount) {
39 if (history.current.length) {
40 // if last element of history !== initial - push initial to history
41 if (history.current[history.current.length - 1] !== initialState) {
42 history.current.push(initialState as I);
43 }
44
45 // if initial history bigger that capacity - crop the first elements out
46 if (history.current.length > capacity) {
47 history.current = history.current.slice(history.current.length - capacity);
48 }
49 } else {
50 // initiate the history with initial state
51 history.current.push(initialState as I);
52 }
53
54 historyPosition.current = history.current.length && history.current.length - 1;
55 }
56
57 const setState = useCallback(
58 (newState: IHookStateSetAction<S>): void => {
59 innerSetState((currentState) => {
60 newState = resolveHookState(newState, currentState);
61
62 // is state has changed
63 if (newState !== currentState) {
64 // if current position is not the last - pop element to the right
65 if (historyPosition.current < history.current.length - 1) {
66 history.current = history.current.slice(0, historyPosition.current + 1);
67 }
68
69 historyPosition.current = history.current.push(newState as I) - 1;
70
71 // if capacity is reached - shift first elements
72 if (history.current.length > capacity) {
73 history.current = history.current.slice(history.current.length - capacity);
74 }
75 }
76
77 return newState;
78 });
79 },
80 [state, capacity]

Callers 2

getHookFunction · 0.90
DemoFunction · 0.90

Calls 2

useFirstMountStateFunction · 0.90
resolveHookStateFunction · 0.90

Tested by 1

getHookFunction · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…