createContextStore
Creates a store powered by context, allowing you to expose state to specific parts of your React application.
Using this approach over the global createStore approach allows you to create multiple stores. Each store can encapsulate differing state needs for branches/features of your application. This may be especially useful for larger scale applications, or when employing code splitting techniques.
const Counter = createContextStore({
count: 0,
increment: action(state => {
state.count += 1;
})
})
Arguments
The following arguments are accepted:
model
(Object | (initialData: any) => Object, required)The model representing your store.
Alternatively this can be a function that accepts
initialData
. TheinitialData
can be provided as a prop to theProvider
. This allows additional runtime configuration/overrides against your model.config
(Object, not required)Custom configuration for your store. Please see the StoreConfig API documentation for a full list of configuration options.
Returns
When executed you will receive a store container that contains the following properties:
Provider
(Component, required)The React component that allows you to wrap a specific part of your React app in order to expose the store state to it. You can wrap as much or as little of your React app as you like.
If you render multiple instances of this provider component each instance will have it's own unique state. This may be handy in some cases, but in most cases you will likely only have one instance of your provider rendered.
<Counter.Provider> <App /> </Counter.Provider>
The provider accepts the following props:
initialData
(Any, not required)Allows you to provide additional data used to initialise your store's model. This needs to be used in conjunction with the function form of defining your model.
<Counter.Provider initialData={{ count: 1 }}> <App /> </Counter.Provider>
useStoreState
(Function, required)A hook allowing you to access the state of your store.
function CountDisplay() { const count = Counter.useStoreState(state => state.count); return <div>{count}</div> }
This hook shares all the same properties and features of the global
useStoreState
hook.useStoreActions
(Function, required)A hook allowing you to access the actions of your store.
function CountIncButton() { const increment = Counter.useStoreActions(actions => actions.increment); return <button onClick={increment}>+</button> }
This hook shares all the same properties and features of the global
useStoreActions
hook.useStoreDispatch
(Function, required)A hook allowing you to access the dispatch of your store.
function CountIncButton() { const dispatch = Counter.useStoreDispatch(); return <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button> }
This hook shares all the same properties and features of the global
useStoreDispatch
hook.useStoreRehydrated
(Function, required)A hook allowing you to access the rehydration status of the store. Only useful when utilising
persist
within your model.function App() { const rehydrated = Counter.useStoreRehydrated(); return rehydrated ? <div>My App</div> : <div>Loading...</div>; }
This hook shares all the same properties and features of the global
useStoreRehydrated
hook.useStore
(Function, required)A hook allowing you to access the store. We recommend that this only be used within exceptional use cases.
function MyCounter() { const store = Counter.useStore(); store.getState(); return null; }
This hook shares all the same properties and features of the global
useStore
hook.
Example
This examples shows how to create a context store and integrate it with your React application.
const Counter = createContextStore({
count: 0,
inc: action(state => {
state.count += 1;
})
})
function MyCounter() {
const count = Counter.useStoreState(state => state.count);
const increment = Counter.useStoreActions(actions => actions.inc);
return (
<>
<div>{count}</div>
<button onClick={() => increment()} type="button"> + </button>
</>
)
}
ReactDOM.render(
<Counter.Provider>
<MyCounter />
</Counter.Provider>,
document.querySelector('#app')
);
Using multiple stores
This example demonstrates how you can use multiple context stores within your React application.
const Counter = createContextStore({
count: 0,
inc: action(state => {
state.count += 1;
})
})
const Todos = createContextStore({
items: [],
addTodo: action((state, text) => {
state.items.push(text)
})
})
ReactDOM.render(
<>
<Counter.Provider>
<CounterApp />
</Counter.Provider>
<Todos.Provider>
<TodosApp />
</Todos.Provider>
</>,
document.querySelector('#app')
);
Nesting multiple stores
This example shows how you can nest multiple context stores.
const Counter = createContextStore({
count: 0,
inc: action(state => {
state.count += 1;
})
})
const Todos = createContextStore({
items: [],
addTodo: action((state, text) => {
state.items.push(text)
})
})
ReactDOM.render(
<Counter.Provider>
<Todos.Provider>
<App />
</Todos.Provider>
</Counter.Provider>,
document.querySelector('#app')
);
Customising your model at runtime
This example shows how you can use the initialData
prop of your context store's Provider
in order to customise your model at runtime.
// The initial data will be received here
// 👇
const Counter = createContextStore(initialData => ({
count: initialData.count,
inc: action(state => {
state.count += 1;
})
}));
ReactDOM.render(
// Provide some initial data to your model instantiation
// 👇
<Counter.Provider initialData={{ count: 1 }}>
<CounterApp />
</Counter.Provider>,
document.querySelector('#app')
);