import { StateProvider, useGetState } from './state';
const MyComp = () => {
const [state, actions] = useGetState();
[...]
};
const App = () => {
return (
<StateProvider>
<MyComp />
</StateProvider>
);
};
Last active
August 16, 2020 14:27
-
-
Save fiuzagr/91be100759c6d5d1f4e735f7802eb17f to your computer and use it in GitHub Desktop.
Simple React Flux with Hooks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export const RESET_STATE = 'RESET_STATE'; | |
| export const SET_ONBOARDING = 'SET_ONBOARDING'; | |
| export const SET_OPEN_MENU = 'SET_OPEN_MENU'; | |
| export const SET_FONT_SIZE = 'SET_FONT_SIZE'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as types from './action-types'; | |
| const creator = (type) => (dispatch) => (payload, meta = {}) => { | |
| console.debug('ACTION', type, { payload, meta }); | |
| return dispatch({ type, payload, meta }); | |
| }; | |
| export const resetState = creator(types.RESET_STATE); | |
| export const setOnboarding = creator(types.SET_ONBOARDING); | |
| export const setOpenMenu = creator(types.SET_OPEN_MENU); | |
| export const setFontSize = creator(types.SET_FONT_SIZE); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export default { | |
| onboarding: false, | |
| openMenu: null, | |
| fontSize: 'medium', | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as types from './action-types'; | |
| const resetState = (_, { payload }) => payload; | |
| const createSimpleReducer = (field) => (state, { payload }) => ({ | |
| ...state, | |
| [field]: payload, | |
| }); | |
| const setOnboarding = createSimpleReducer('onboarding'); | |
| const setOpenMenu = createSimpleReducer('openMenu'); | |
| const setFontSize = createSimpleReducer('fontSize'); | |
| export default { | |
| [types.RESET_STATE]: resetState, | |
| [types.SET_ONBOARDING]: setOnboarding, | |
| [types.SET_OPEN_MENU]: setOpenMenu, | |
| [types.SET_FONT_SIZE]: setFontSize, | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, { | |
| useState, | |
| useEffect, | |
| createContext, | |
| useContext, | |
| useReducer, | |
| } from 'react'; | |
| import { node } from 'prop-types'; | |
| import useActions from './use-actions'; | |
| import reducers from './reducers'; | |
| import initialState from './initial-state'; | |
| const dataStorage = localForage.createInstance({ | |
| name: 'myStorage', | |
| storeName: 'data', | |
| }); | |
| const reducer = (state, action) => { | |
| if (reducers[action.type]) { | |
| const newState = reducers[action.type](state, action); | |
| console.debug('REDUCER', action.type, { state, newState }); | |
| return newState; | |
| } | |
| return state; | |
| }; | |
| export const StateContext = createContext(); | |
| // exposes [state, actions] from context | |
| export const useGetState = () => useContext(StateContext); | |
| export const StateProvider = ({ children }) => { | |
| const [state, dispatch] = useReducer(reducer, initialState); | |
| const [loadingState, setLoadingState] = useState(true); | |
| const actions = useActions(dispatch); | |
| // reset state with state in storage | |
| useEffect(() => { | |
| if (loadingState) { | |
| dataStorage | |
| .getItem('state') | |
| .then((state) => state && actions.resetState(state)) | |
| .catch(console.error) | |
| .finally(() => setLoadingState(false)); | |
| } | |
| // useful for debug | |
| if (process.env.NODE_ENV === 'development') { | |
| window.__ACTIONS = actions; | |
| } | |
| }, [loadingState, actions]); | |
| // save new state on storage and preserve previous state | |
| useEffect(() => { | |
| if (!loadingState) { | |
| dataStorage | |
| .getItem('state') | |
| .then((previousState) => | |
| dataStorage.setItem('previousState', previousState) | |
| ) | |
| .then(() => dataStorage.setItem('state', state)) | |
| .catch(console.error); | |
| } | |
| }, [state, loadingState]); | |
| return loadingState ? ( | |
| <div>Loading...</div> | |
| ) : ( | |
| <StateContext.Provider value={[state, actions]}> | |
| {children} | |
| </StateContext.Provider> | |
| ); | |
| }; | |
| StateProvider.propTypes = { | |
| children: node.isRequired, | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useMemo } from 'react'; | |
| import * as actions from './actions'; | |
| const useActions = (dispatch) => | |
| useMemo(() => Object.values(actions).map((action) => action(dispatch)), [dispatch]); | |
| export default useActions; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment