React Context Stores provides light-weight context stores that can be used by react apps for global state management with redux-like features but using purely react components.
This React Context Stores was created to provide light-weight alternatives for setting up react Context API or using React-Redux library for medium to light weight apps (or create-react-app) need for global state management also with redux-like features and does not use any external libraries. The React app demonstrates a working example on how to use the react-context-stores
. The react store uses the useContext and useReducer react hooks to implement an app state management system. Therefore your react app version should support this hooks as well.
npm install --save react-context-stores
react-context-stores
provides 3 types of store classes.
Import the ContextStore
class and initialize the store outside the react component. Wrap the components you wish to provide store to via .Provider
component of the store instance then pass the store data to the .Provider
via the value
prop. Finally, export the ContextStore
instance to be accessible from other component.
// App.jsx
import React from 'react';
import { ContextStore } from 'react-context-stores';
import Counter from './components/Counter/Counter';
// Initialize the store with a name and export the store instance
export const contextStore = new ContextStore('Context Store');
// This could be any component
const App = () => {
const [counter, setCounter] = useState(0);
// Wrap the children with the provider property of the store
// Pass the value to be provided globally to the children components to the *value* prop
return (
<contextStore.Provider value={{ counter, setCounter }}>
<h3>Context Store Example</h3>
<Counter />
</contextStore.Provider>
);
}
export default App;
Access the store data in the Counter
component. .useStore
method of the store instance returns an object of storeStateObject
// ./components/Counter/Counter.jsx
import React from 'react'
// import the store instance
import { contextStore } from '../../App'
const Counter = () => {
// Destruct the store data
const { counter, setCounter } = contextStore.useStore()
// Use the store data
return (
<div>
<div>{counter}</div>
<div>
<button onClick={() => setCounter(counter1 - 1)}>-</button>
<button onClick={() => setCounter(0)}>reset</button>
<button onClick={() => setCounter(counter1 + 1)}>+</button>
</div>
</div>
)
}
export default Counter
ContextStore
can be instantiated as many as needed and in any part of the application.
Context redux store provides a redux like interface.
Firstly, we need to setup the store.
// ./store/counterSlice/index.js
// Store data instance
export const initialState = {
counter: 0
}
// Reducer to update the store
export const reducer = (state, action) => {
switch (action.type) {
case 'CHANGE':
return { ...state, counter: state.counter + action.payload }
case 'RESET':
return { ...state, counter: 0 }
default:
return state
}
}
// Actions object
export const actions = {
change: (payload) => ({ type: 'CHANGE', payload }),
reset: { type: 'RESET' }
}
Import the ContextReduxStore
class and initialize the store outside the react component. Wrap the components you wish to provide store to via .Provider
component of the store instance then pass the store data to the .Provider
via the value
prop. The value
must be an array of [stateObject, reducerFuction]
. Finally, export the ContextReduxStore
instance to be accessible from other component.
// App.jsx
import React from 'react';
import { ContextReduxStore } from 'react-context-stores';
import { initialState, reducer } from './store/counterSlice'
import Counter from './components/Counter/Counter';
// Initialize the store with a name and export the store instance
export const contextReduxStore = new ContextReduxStore('Context Redux Store');
// This could be any component
const App = () => {
// Wrap the children with the provider property of the store
// Pass the value to be provided globally to the children components to the *value* prop
return (
<contextReduxStore.Provider value={[initialState, reducer]}>
<h3>Context Redux Store Example</h3>
<Counter />
</contextReduxStore.Provider>
);
}
export default App;
Access the store data in the Counter
component. .useStore
method of the store instance returns an array of [stateObject, dispatchFunction]
.
// ./components/Counter/Counter.jsx
import React from 'react';
import { actions } from '../../store/counterSlice';
// import the store instance
import { contextReduxStore } from '../../App';
const Counter = () => {
// Destruct the store data
const [ state, dispatch ] = contextReduxStore.useStore();
// Use the store data
return (
<div>
<div>{ state.counter }</div>
<div>
<button onClick={() => dispatch(actions.change(-1))}>-</button>
<button onClick={() => dispatch(actions.reset}>reset</button>
<button onClick={() => dispatch(actions.change(+1)}>+</button>
</div>
</div>
);
}
export default Counter;
ContextReduxStore
can be instantiated as many as needed and in any part of the application.
Context combine store provides a redux like interface with the combine store feature.
Having setup the store(s), we need to combine the store.
// ./store/index.js
import { counterInitialState, counterReducer } from './counterSlice'
import { otherInitialState, otherReducer } from './otherSlice'
/**
* Object that combines different store slices
*/
const combineStoreSetup = {
// The format for combining store is as follows
// sliceName: [sliceInitialState, sliceReducer ]
counterStore: [counterInitialState, counterReducer],
otherStore: [otherInitialState, otherReducer]
}
export default combineStoreSetup
Import the ContextCombineStore
class and initialize the store outside the react component. Then, Wrap the components you wish to provide store to via .Provider
component of the store instance then pass the store data to the .Provider
via the value
prop. The value
must be an object of {...sliceNames}
, where each slice is an array of [sliceStateObject, sliceReducerFunction]
. Finally, export the ContextCombineStore
instance to be accessible from other component.
// App.js
import React from 'react';
import { ContextCombineStore } from 'react-context-stores';
import combineStoreSetup from './store'
import Counter from './components/Counter/Counter';
// Initialize the store with a name and export the store instance
export const contextCombineStore = new ContextCombineStore('Context Combine Store');
.
// This could be any component
const App = () => {
// Wrap the children with the provider property of the store
// Pass the value to be provided globally to the children components to the *value* prop
return (
<contextCombineStore.Provider value={combineStoreSetup}>
<h3>Context Combine Store Example</h3>
<Counter />
</contextCombineStore.Provider>
);
}
export default App;
Access the store data in the Counter
component. .useStore
method of the store instance returns an object of { ...sliceNames }
where each slice is an array of [sliceStateObject, sliceDispatchFunction]
.
// ./components/Counter/Counter
import React from 'react';
import { actions } from '../../store/counterSlice';
// import the store instance
import { contextCombineStore } from '../../App';
const Counter = () => {
// Destruct the stores data
const { counterStore, /* otherStore */ } = contextCombineStore.useStore();
// Access any of the stores
const [ state, dispatch ] = counterStore;
// Use the store data
return (
<div>
<div>{ state.counter }</div>
<div>
<button onClick={() => dispatch(actions.change(-1))}>-</button>
<button onClick={() => dispatch(actions.reset}>reset</button>
<button onClick={() => dispatch(actions.change(+1)}>+</button>
</div>
</div>
);
}
export default Counter;
ContextCombineStore
can be instantiated as many as needed and in any part of the application.
MIT ©
An example use of the store can be found in the example folder.