35
loading...
This website collects cookies to deliver better user experience
useState
that will store our state and update it, and then we will use react context to pass it down to components.StoreContext
and in its value the first item will be the store itself and the second item will be setStore so that we can update it.import React, { createContext, useContext, useMemo, useState } from 'react'
const StoreContext = createContext()
export const StoreProvider = ({ children, initialState }) => {
const [store, setStore] = useState(initialState)
const contextValue = useMemo(() => [store, setStore], [store])
return (
<StoreContext.Provider value={contextValue}>
{children}
</StoreContext.Provider>
)
}
export const useStore = () => {
return useContext(StoreContext)
}
export default StoreContext
useState
and at one point it will become a PIA to update your store using setStore. So let's add a useReducer
in here and now our code looks something like,import React, { createContext, useContext, useMemo, useReducer } from 'react'
const StoreContext = createContext()
export const StoreProvider = ({ children, initialState, reducer }) => {
const [store, dispatch] = useReducer(reducer, initialState)
const contextValue = useMemo(() => [store, dispatch], [store])
return (
<StoreContext.Provider value={contextValue}>
{children}
</StoreContext.Provider>
)
}
export const useStore = () => {
return useContext(StoreContext)
}
export default StoreContext
useDispatch
hook.import React, { createContext, useContext, useReducer } from 'react'
const StoreContext = createContext()
export const DispatchContext = createContext()
export const StoreProvider = ({ initialState, reducer, children }) => {
const [store, dispatch] = useReducer(reducer, initialState)
return (
<DispatchContext.Provider value={dispatch}>
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
</DispatchContext.Provider>
)
}
export const useStore = () => {
return useContext(StoreContext)
}
export const useDispatch = () => {
return useContext(DispatchContext)
}
export default StoreContext
App
first in DispatchContext
and then StoreContext
and then in our componentimport React, { useRef } from 'react'
import { useDispatch, useStore } from '@state/context-reducer'
const Example = () => {
const dispatch = useDispatch()
const store = useStore()
return (
<div className="my-3">
<p>{JSON.stringify(store)}</p>
<button onClick={() => dispatch({ type: 'increment' })}>
Dispatch
</button>
</div>
)
}
export default Example
makeStore
that takes in the reducer and initialState, and gives us a provider, a useStore and a useDispatch, so that we can easily make multiple stores.import React, { createContext, useContext, useReducer } from 'react'
export default function makeStore(reducer, initialState) {
const StoreContext = createContext(null)
const DispatchContext = createContext(null)
const StoreProvider = ({ children }) => {
const [store, dispatch] = useReducer(reducer, initialState)
return (
<DispatchContext.Provider value={dispatch}>
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
</DispatchContext.Provider>
)
}
const useStore = () => {
return useContext(StoreContext)
}
const useDispatch = () => {
return useContext(DispatchContext)
}
return [StoreProvider, useStore, useDispatch]
}
const [LayoutStore, useLayout, useLayoutDispatch] = makeStore(layoutReducer, { menuOpen: false })
const [TodoStore, useTodo, useTodoDispatch] = makeStore(todosReducer, [])
makeStore
function:export default function makeStore(reducer, initialState, key) {
const StoreContext = createContext(null)
const DispatchContext = createContext(null)
let finalInitialState = null
try {
finalInitialState = JSON.parse(localStorage.getItem(key)) || initialState
} catch(e) {}
const finalReducer = (state, action) => {
const newState = reducer(state, action)
localStorage.saveItem(key, JSON.stringify(newState))
return newState
}
// And now we use finalInitialState and finalReducer
// instead of reducer and initialState
}