0.2.0 • Published 5 years ago

react-hook-contexts v0.2.0

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

react-hook-contexts

React-hook-contexts is a new way to use useContext better.

build status npm version license

Features

  • Easy state management with useState and useReducer.
  • Optimally split context to prevent unnecessary renders.
  • useSelector function.
  • Support for SSR.

Why

The context API allows you to create a simple store in combination with hooks such as useState and useReducer.

However, it can lead to unnecessary renders if you don't split the context with proper granularity. It also doesn't have a feature like redux's useSelector. That means you have to memo. Please see the solutions.

On the other hand, while redux is appropriate for managing large amounts of state, I don't think it's necessary for small projects to adopt such a large library.

This library is intended to avoid the implementation costs of redux and also to prevent unnecessary renders, which is a problem with the context API.

Installation

You can install the package from npm.

npm install react-hook-contexts

or using yarn.

yarn add react-hook-contexts

Usage

General

import React from "react";
import { createUseStateContexts } from "react-hook-contexts";

// You can add global state here. easy !!
const [store, ContextProviders] = createUseStateContexts({
  counter: 0,
  message: "",
  app: {
    name: "react-hook-contexts",
    description: "A easy global state management library",
  },
});

const App = () => {
  return (
    <ContextProviders>
      <AppName />
      <Counter />
      <CounterButton />
    </ContextProviders>
  );

  // To prevent unnecessary renders,
  // the context is automatically split in the virtual DOM as follows
  //
  // <CounterStateContext>
  //   <CounterDispatchContext>
  //     <MessageStateContext>
  //       <MessageDispatchContext>
  //         <AppStateContext>
  //           <AppDispatchContext>
  //             <AppName />
  //             <Counter />
  //             <CounterButton />
  //           </AppDispatchContext>
  //         </AppStateContext>
  //       </MessageDispatchContext>
  //     </MessageStateContext>
  //   </CounterDispatchContext>
  // </CounterStateContext>
};

const Counter = () => {
  // You can get the state value of the context as follows
  const counter = store.counter.state();

  return <p>counter: {counter}</p>;
};

const CounterButton = () => {
  // It only gets the dispatch; separating the state and the dispatch prevents extra renders.
  const setCounter = store.counter.dispatch();

  return (
    <>
      <button onClick={() => setCounter((counter) => counter + 1)}>+ 1</button>
      <button onClick={() => setCounter((counter) => counter - 1)}>- 1</button>
    </>
  );
};

const AppName = () => {
  // Like the redux useSelector API, you can retrieve only the state you need.
  // And there are no unnecessary renders.
  const name = store.app.state((app) => app.name);

  return <p>App: {name}</p>;
};

export default App;

createUseStateContexts API

createUseStateContexts is generated by executing the values of the passed object as useState arguments, each of which is divided with appropriate granularity as a value of context.

import React from "react";
import { createUseStateContexts } from "react-hook-contexts";

const [store, ContextProviders] = createUseStateContexts({
  counter: 0,
  message: "",
  app: {
    name: "react-hook-contexts",
    description: "A easy global state management library",
  }
});

You can use it as follows.

const counter = store.counter.state();
// 0

const message = store.message.state();
// ""

const appState = store.app.state();
// {
//   name: "react-hook-contexts",
//   description: "A easy global state management library",
// }

const appName = store.app.state(app => app.name)
// "react-hook-contexts"

const counterDispatch = store.counter.dispatch()
const messageDispatch = store.message.dispatch()
const appDispatch = store.app.dispatch()
// Each of the dispatch functions

createUseReducer API

createUseReducerContexts is createUseStateContexts as well as generated by executing the values of the passed object as useReducer arguments, each of which is divided with appropriate granularity as a value of context.

import React from "react";
import { createUseReducerContexts } from "react-hook-contexts";

const initialState = {
  count: 0,
};

const ActionType = {
  INCREMENT: "INCREMENT",
  DECREMENT: "DECREMENT",
} as const;

type CounterAction = {
  type: keyof typeof ActionType;
};

const reducer: React.Reducer<typeof initialState, CounterAction> = (
  state,
  action
) => {
  switch (action.type) {
    case ActionType.INCREMENT: {
      return {
        count: state.count + 1,
      };
    }

    case ActionType.DECREMENT: {
      return {
        count: state.count - 1,
      };
    }

    default: {
      return state;
    }
  }
};

export const [store, ContextProviders] = createUseReducerContexts({
  counter: {
    reducer,
    initialState,
  }
});

The usage is the same as useCreateReducerContexts API.

Examples

CreateUseStateContexts API example

This is an example of a counter app that uses the createUseStateContexts API.

Notice that each time you increase/decrease the count, only the render of the Counter comport is running. (No unnecessary renders are happening.)


CreateUseReducerContexts API example

Similar to the example above, this is an example of a counter app using the createUseReducerContexts API.


License

MIT © kqito

0.2.1

5 years ago

0.2.0

5 years ago

0.1.6

5 years ago

0.1.5

5 years ago

0.1.4

5 years ago

0.1.3

5 years ago

0.1.2

5 years ago

0.1.0

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago