use-global-hook-context v0.3.0
use-global-hook-context
Use-global-hook-context is a new way to use useContext
better.
Features
- Easy state management with
useState
anduseReducer
. - 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 use-global-hook-context
or using yarn.
yarn add use-global-hook-context
Usage
General
import React from "react";
import { createUseStateContext } from "use-global-hook-context";
// You can add global state here. easy !!
const [useGlobalState, useGlobalDispatch, ContextProvider] = createUseStateContext({
counter: 0,
message: "",
app: {
name: "use-global-hook-context",
description: "A easy global state management library",
},
});
const App = () => (
<ContextProvider>
<AppName />
<Counter />
<CounterButton />
</ContextProvider>
)
const Counter = () => {
// You can get the state value of the context as follows
const counter = useGlobalState.counter();
return <p>counter: {counter}</p>;
};
const CounterButton = () => {
// It only gets the dispatch; separating the state and the dispatch prevents extra renders.
const dispatch = useGlobalDispatch();
return (
<>
<button onClick={() => dispatch.counter((counter) => counter + 1)}>+ 1</button>
<button onClick={() => dispatch.counter((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 = useGlobalState.app((app) => app.name);
return <p>App: {name}</p>;
};
export default App;
createUseStateContext
API
createUseStateContext
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 { createUseStateContext } from "use-global-hook-context";
const [useGlobalState, useGlobalDispatch, ContextProvider] = createUseStateContext({
counter: 0,
message: "",
app: {
name: "use-global-hook-context",
description: "A easy global state management library",
}
});
You can use it as follows.
const counter = useGlobalState.counter();
// 0
const message = useGlobalState.message();
// ""
const appState = useGlobalState.app();
// {
// name: "use-global-hook-context",
// description: "A easy global state management library",
// }
const appName = useGlobalState.app(app => app.name)
// "use-global-hook-context"
const dispatch = useGlobalDispatch()
// Each of the dispatch functions
// {
// counter: ƒ dispatchAction,
// message: ƒ dispatchAction,
// app: ƒ dispatchAction
// }
createUseReducerContext
API
createUseReducerContext
is createUseStateContext
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 { createUseReducerContext } from "use-global-hook-context";
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 [useGlobalState, useGlobalDispatch, ContextProvider] = createUseReducerContext({
counter: {
reducer,
initialState,
}
});
The usage is the same as useCreateReducerContext
API.
Examples
CreateUseStateContext API example
This is an example of a counter app that uses the createUseStateContext
API.
Notice that each time you increase/decrease the count, only the render of the Counter comport is running. (No unnecessary renders are happening.)
CreateUseReducerContext API example
Similar to the example above, this is an example of a counter app using the createUseReducerContext
API.
License
5 years ago