Skip to content

Latest commit

 

History

History
120 lines (98 loc) · 2.65 KB

react_global_store.md

File metadata and controls

120 lines (98 loc) · 2.65 KB

source : Samuel Resua (https://medium.com/@samuelresua/global-state-machine-with-react-context-afd0d5475592)

App.js

import ReactDOM from 'react-dom';
import Store from './store';

const App = () => (
  <Store>
    <ComponentExample />
  </Store>
);

ReactDOM.render(<App />, document.getElementById('root'));

store/contextExample.js

const contextExample = {
  name: 'Example',
  initialState: {
    param: 'pouet',
  },
  reducer: (state, action) => {
    switch (action.type) {
      case 'actionType':
        // Update state
        const newState = {
          ...state, 
          params: action.payload,
        };
        return newState;
        
      default:
        return state;
    }
  },
}

export default contextExample;

store/createStore.js

const createStore = (config = []) => {
  // Reduce into an object of providers and context
  const { contexts, providers } = config.reduce(
    (acc, { name, initialState, reducer }) => {
      // Context
      const stateContext = React.createContext();
      const dispatchContext = React.createContext();

      // Create provider
      const Provider = ({ children }) => {
        const [state, dispatch] = React.useReducer(reducer, initialState);
        
        return (
          <State.Provider value={state}>
            <Dispatch.Provider value={dispatch}>{children}</Dispatch.Provider>
          </State.Provider>
        )
      }

      // Set and return
      acc.providers.push(<Provider />);
      acc.context[name] = { state: stateContext, dispatch: dispatchContext };
      
      return acc;
    },
    {
      providers: [],
      contexts: {},
    }
  )

  // Create store
  const Store = ({ children: initial }) =>
    providers.reduce(
      (children, parent) => React.cloneElement(parent, { children }),
      initial
    );

  return { Store, ...contexts };
}

export default createStore;

store/index.js

import createStore from './createStore';
import contextExample from './contextExample';
import contextExampleBis from './contextExampleBis';

const { Store, ...contexts } = createStore([contextExample, contextExampleBis]);

export contexts;
export default Store;

components/ComponentExample.js

import { Example } from '../store';

const ComponentExample = () => {
  const { param } = React.useContext(Example.state);
  const dispatch = React.useContext(Example.dispatch);
  
  const handleClick = () => {dispatch('actionType', { payload: 'pouik' })};

  return (
    <div>
      <p>Context param: {param}</p>
      <button onClick={handleClick} >Click me</button>
    </div>
  );
}

export default ComponentExample;