1.1.0 • Published 1 year ago

@utilityjs/create-store-context v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

A React store-context that manages states of a tree where unnecessary re-renders have been omitted thanks to the Pub/Sub design pattern.

license npm latest package npm downloads types

npm i @utilityjs/create-store-context | yarn add @utilityjs/create-store-context

How does it work?

The <StoreProvider> works as a Publisher and each useStore is a Subscriber. So when the state changes, only necessary Subscribers will be re-rendered. Since we are using useRef instead of useState the Publisher itself won't re-render.

This way we guarantee that only the necessary components need to be re-rendered.

Usage

import createStoreContext from "@utilityjs/create-store-context";

interface StoreState {
  count: number;
  log: () => void;
  increase: (amount: number) => void;
}

const { useStore, StoreProvider } = createStoreContext<StoreState>(
  (setState, getState) => ({
    count: 0,
    log: () => void getState().count,
    increase: amount =>
      setState(state => ({ ...state, count: state.count + amount }))
  })
);

const Controls = () => {
  const increase = useStore(state => state.increase);

  return (
    <div>
      <button onClick={() => increase(1)}>Increase by 1</button>
      <button onClick={() => increase(5)}>Increase by 5</button>
      <button onClick={() => increase(10)}>Increase by 10</button>
    </div>
  );
};

const Display = () => {
  const { count, log } = useStore(state => ({
    count: state.count,
    log: state.log
  }));

  log();

  return <div>Count: {count}</div>;
};

const Container = () => (
  <div>
    <h2>Container</h2>
    <Controls />
    <Display />
  </div>
);

const App = () => {
  return (
    <main id="main">
      <div id="main-wrapper">
        <StoreProvider>
          <h1>App</h1>
          <Container />
        </StoreProvider>
      </div>
    </main>
  );
};

API

createStoreContext(stateFactory)

type StateSelector<State, PartialState> = (
  store: State
) => PartialState;

type UseStoreHook<State> = <PartialState = State>(
  selector: StateSelector<State, PartialState>
) => PartialState;

type StateFactory<S> = (
  setState: (setter: (prevState: S) => S) => void,
  getState: () => S
) => S;

declare const createStoreContext: <S>(stateFactory: StateFactory<S>) => {
  StoreProvider: (props: { children: React.ReactNode }) => JSX.Element;
  useStore: UseStoreHook<S>;
};

stateFactory

An initialization function to initialize the states.