Custom Hooks
useStore

useStore

Simple, typesafe and easy to use global/local store for React. It has no dependencies besides React itself.

Counter

This counter is using useStore custom hook, to show and update its state

current state: 0

Installation

Copy whole useStore folder from repository. You can start using it right away, without any dependency.

Usage

Whole usage is based on two elements: StoreProvider and useStore hook. Store provider needs to wrap the component that will use the store, and useStore hook is used to access the store state and dispatch function.

demo.tsx
import { StoreProvider, useStore } from "../hooks/useStore";
 
const NestedComponent = () => {
  const { state, dispatch } = useStore();
 
  const handleClick = () => {
    dispatch({ type: "Set", payload: 10 });
  };
 
return (
    <div>
      State: {state.counter}
      <button onClick={handleClick}>
        Set counter to 10!
      </button>
    </div>
  );
};
 
const Example = () => {
  return (
    <StoreProvider>
      <NestedComponent />
    </StoreProvider>
  );
};

Configuration

storeState.tsx

This file is used to define the initial state of the store. It should contain the type of the store state and the initial value.

storeState.ts
export type StoreStateType = {
  counter: number;
};
 
export const initialStoreState: StoreStateType = {
  counter: 0,
};

reducer.tsx

This file is used to define the reducer function. It should contain the type of possible actions and the reducer function itself. Each action should have a unique type and a payload if needed. Make sure to spread the state object when returning a new state.

reducer.ts
import { StoreStateType, initialStoreState } from "./storeState";
 
type PossibleActions = {
  Increase: { type: "Increase" };
  Decrease: { type: "Decrease" };
  Set: { type: "Set"; payload: number };
  Reset: { type: "Reset" };
};
 
export type ActionType = PossibleActions[keyof PossibleActions];
 
export const reducer = (state: StoreStateType, action: ActionType) => {
  switch (action.type) {
    case "Increase":
      return { ...state, counter: state.counter + 1 };
    case "Decrease":
      return { ...state, counter: state.counter - 1 };
    case "Set":
      return { ...state, counter: action.payload };
    case "Reset":
      return initialStoreState;
    default:
      return state;
  }
};

API

There is only one parameter for StoreProvider component: initialState. It is optional and can be used to provide a custom initial state for the store.

demo.tsx
<StoreProvider initialState={{ counter: 10 }}>
  <NestedComponent />
</StoreProvider>