create first draft
This commit is contained in:
parent
dc35932027
commit
30aa1e95dc
66
lib/context-reducer.js
Normal file
66
lib/context-reducer.js
Normal file
@ -0,0 +1,66 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useMemo,
|
||||
useRef,
|
||||
useReducer
|
||||
} from 'react'
|
||||
|
||||
function createStore({ reducer = {}, actions = {}, initialState = {} }) {
|
||||
const context = createContext(initialState)
|
||||
const reducerFn =
|
||||
typeof reducer === 'function' ? reducer : makeReducerFn(reducer)
|
||||
|
||||
const StoreProvider = ({ children }) => {
|
||||
const store = useReducer(reducerFn, initialState)
|
||||
const storeRef = useRef(store)
|
||||
const thunks = useMemo(() => createThunks(actions, storeRef), [storeRef])
|
||||
return (
|
||||
<context.Provider value={[store[0], thunks]}>{children}</context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
const useStore = selector => {
|
||||
const [state, actions] = useContext(context)
|
||||
return typeof selector === 'function'
|
||||
? selector(state, actions)
|
||||
: [state, actions]
|
||||
}
|
||||
|
||||
return [StoreProvider, useStore]
|
||||
}
|
||||
|
||||
export default createStore
|
||||
|
||||
/** Returns a set of actions that are bound to the store */
|
||||
function createThunks(actions, storeRef) {
|
||||
const [state, dispatch] = storeRef.current
|
||||
const thunks = {}
|
||||
for (let name of Object.keys(actions)) {
|
||||
thunks[name] = (...args) =>
|
||||
actions[name](...args)({
|
||||
dispatch,
|
||||
state,
|
||||
type: camelToSnakeCase(name).toUpperCase()
|
||||
})
|
||||
}
|
||||
return thunks
|
||||
}
|
||||
|
||||
function makeReducerFn(reducerObj) {
|
||||
return (state, action) => {
|
||||
const { type, ...payload } = action
|
||||
if (typeof reducerObj[type] === 'undefined') return state
|
||||
const newState = reducerObj[type](state, payload)
|
||||
return newState
|
||||
}
|
||||
}
|
||||
|
||||
const camelToSnakeCase = str =>
|
||||
str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
|
||||
|
||||
const [Provider, useStore] = createStore({ reducer: {}, actions: {} })
|
||||
|
||||
export const MyConponent = () => {
|
||||
const [state, actions] = useStore()
|
||||
}
|
Loading…
Reference in New Issue
Block a user