Rename and add logging

context-store
Alfred Melch 5 years ago
parent 3255c42253
commit 7434b1e17e

@ -1,9 +1,13 @@
import React, { createContext, useContext, useMemo, useReducer } from 'react' import React, { createContext, useContext, useMemo, useReducer } from 'react'
/** Takes objects that fully define a store and turns it into a more potent reducer */ /** Takes objects that fully define a store and turns it into a more potent reducer */
export const useReducerStore = storeDef => { export const usePotentReducer = options => {
const { reducer = {}, thunks = {}, initialState } = storeDef const { reducer = {}, thunks = {}, initialState } = options
const reducerFn = useMemo(() => makeReducerFn(reducer), [reducer]) const { onUpdate, logging } = options
const reducerFn = useMemo(
() => makeReducerFn(reducer, { onUpdate, logging }),
[reducer, onUpdate, logging]
)
const [state, dispatch] = useReducer(reducerFn, initialState) const [state, dispatch] = useReducer(reducerFn, initialState)
const _thunks = useMemo(() => bindThunks(thunks, dispatch), [ const _thunks = useMemo(() => bindThunks(thunks, dispatch), [
thunks, thunks,
@ -15,10 +19,10 @@ export const useReducerStore = storeDef => {
/** A ReducerStore Factory that uses React.context /** A ReducerStore Factory that uses React.context
* Used to make a Store accessible through multiple components * Used to make a Store accessible through multiple components
*/ */
export const createStore = storeDef => { export const createStore = options => {
const context = createContext(null) const context = createContext(null)
const Provider = ({ children }) => { const Provider = ({ children }) => {
const store = useReducerStore(storeDef) const store = usePotentReducer(options)
return React.createElement(context.Provider, { value: store }, children) return React.createElement(context.Provider, { value: store }, children)
} }
const useStore = () => useContext(context) const useStore = () => useContext(context)
@ -29,12 +33,16 @@ export const createStore = storeDef => {
* @param {Object} reducer: Object definition of a reducer: {<type>: (state, payload) => <newState>} * @param {Object} reducer: Object definition of a reducer: {<type>: (state, payload) => <newState>}
* @returns {Function}: Proper reducer * @returns {Function}: Proper reducer
*/ */
function makeReducerFn(reducer) { function makeReducerFn(reducer, { onUpdate, logging }) {
return (state, action) => { const noop = state => state
return (prevState, action) => {
const { type, ...payload } = action const { type, ...payload } = action
if (typeof reducer[type] === 'undefined') return state const reducerBranch = reducer[type] || reducer['default'] || noop
const newState = reducer[type](state, payload) const nextState = reducerBranch(prevState, payload)
return newState const stats = { prevState, nextState, action }
typeof onUpdate === 'function' && onUpdate(stats)
if (logging) logger(stats)
return nextState
} }
} }
@ -60,3 +68,13 @@ function patchDispatch(dispatch, type) {
dispatch({ type, ...action }) dispatch({ type, ...action })
} }
} }
/** Log action inspired by redux-logger */
const logger = ({ prevState, action, nextState }) => {
const css = color => `color: ${color}; font-weight: bold;`
console.groupCollapsed(`%c action`, 'color: #9E9E9E', action.type)
console.log('%c prevState ', css('#9E9E9E'), prevState)
console.log('%c action ', css('#03A9F4'), action)
console.log('%c nextState ', css('#4CAF50'), nextState)
console.groupEnd()
}
Loading…
Cancel
Save