react-simple-hook-store
v0.0.6
Published
Implements state management for React using hooks. No Redux, no Mobx, no React Context Api, just React hooks
Downloads
23
Readme
Simple React hook based state management
No Redux, no Mobx, no React Context API, just React hooks. React 16.8+ required.
The project is heavily based on the State Management with React Hooks — No Redux or Context API article and corresponding npm module. This project fixes some issues, adds tests, new features and written in TypeScript.
The idea
Your state is readonly and immutable. The only way to update the state from a component's code is through actions. If you want to update the state from outside a component, you can use store's setState
method. All updates to the state should be immutable (the same way as you do it for React's setState
in class based components). You should define the structure of your state, your actions and start using them in your components.
Installation
$ npm install react-simple-hook-store --save
Or just add dist/react-simple-hook-store.js
in your project through the script reference.
Usage
Define your state structure:
interface IState {
counter: number;
}
Define actions, which modify your state:
interface IActions {
increment: () => void;
}
Create store. It accepts an initial state value as the first argument and your actions as the second.
import { createStore } from "react-simple-hook-store";
const { useStore, store } = createStore<IState, IActions>({
counter: 0,
}, {
increment: (store) => {
store.setState({
counter: store.state.counter + 1,
});
}
});
createStore
returns React hook called useStore
, which you should use in your components. It accepts a map function, which returns subset of the whole state. The second param is actions map function. If you want all actions to be returned, omit this parameter.
const Component = () => {
const [counter, increment] = useStore((s) => s.counter, (a) => a.increment);
return (
<button onClick={() => increment()}>
{counter}
</button>
);
};
counter
will be your "local state" here. Every time other components (or current component) update counter
state variable, the component will get re-rendered. Another way to read it: any updates to counter
global state will cause this component to be re-rendered.
If you want to modify the state outside of React component, you can use store
exported on the previous step.
More examples
Basic usage
This sample contains bare minimum you need to setup to get started with react-simple-hook-store
Async actions
You can have async actions inside your store
Multiple stores
You can have as many stores as your application needs. There are two ways to handle it - either use "namespaces" or simply create separate stores (if your stores are completely unrelated)
Different ways to access your store from components
useStore
hook has several overloads which might be useful in different situations.
Todo App
This sample showcases full Todo App. The store contains all todo items as an array and filter state. You don't necessarily need global state for your todos, but just for the demo purposes it's ok. It demonstrates how to update state correctly (immutably, including arrays).
API
createStore<IStore, IActions>(initialState, actions)
Creates a store.
Arguments
initialState
:object
, the initial state, supports multilevel, i.e.{ appState: { value: "myvalue" }, navigation: { active: "node1" } }
actions
:StoreActions<IState, IActions>
actions map. You use actions to modify state from components. For example:interface IState { counter: number; } interface IActions { increment: () => void; } const actions: StoreActions<IState, IActions> = { increment: store => { store.setState({ counter: store.state.counter + 1 }); } }
Return value
Object with properties (more on every property below):
useStore
- React hook to be used inside React functional componentsstore
- store instance, might be useful outside of React componentsbatchUpdates
- function wrapper to batch multiple setState to reduce the number of re-renders. For advanced performance tunning, in most cases you don't need it. More info below.
useStore(mapState, mapActions)
Arguments
mapState
: a function, which returns a subset of the original state. When omitted,undefined
will be returned. Current component will be re-rendered only if the result ofmapState
will be changed.mapActions
: a function, which returns a subset of actions. When omitted, all actions will be returned
Return value
An array with two values:
- [0]: the result of
mapState
function, orundefined
ifmapState
isundefined
. - [1]: the result of
mapActions
function or all actions ifmapActions
isundefined
store
object
Properties:
state
- readonly state objectactions
- all store actions
Methods:
setState
- a function which accepts subset of original state to modify the state. Works the same way as React'ssetState
in class based components, i.e. merges provided value with original state.
batchUpdates
A function, which accepts a callback. Inside that callback you can use as many store.setState
as you wish. This will cause only one render inside React components.
When it might be useful? If you perform multiple state updates as a result of async function (or as a result of timeout function). By default React will re-render your component as a result of every call to setState
. More info in this React issue.