Last active
January 22, 2020 20:27
-
-
Save jabney/47ec952b82d354e77dde5703d2603bdd to your computer and use it in GitHub Desktop.
micro-react-redux: a minimal implementation of react-redux style provider and connect function
This file contains 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
/** | |
* Minimal implementation of react-redux style provider and connect function. | |
*/ | |
import React, { useState, useEffect, useContext } from 'react' | |
const StoreContext = React.createContext(null) | |
/** | |
* Wraps root component for providing store context, e.g., | |
* | |
* <StoreProvider store={store}> | |
* <App /> | |
* </StoreProvider> | |
*/ | |
export const StoreProvider = ({ children, store }) => ( | |
<StoreContext.Provider value={store}>{children}</StoreContext.Provider> | |
) | |
/** | |
* Connect an individual component to the store, a la react-redux. | |
* | |
* @param {(state: any, props?: any) => {[key: string]: any}} mapState | |
* @param {(dispatch: (action: any) => void) => {[key: string]: (...args: any) => void}} mapDispatch | |
*/ | |
export const connect = (mapState, mapDispatch) => (WrappedComponent) => (props) => { | |
const [, update] = useState(null) | |
// Get the store context (requires use of StoreProvider). | |
const store = useContext(StoreContext) | |
// Create a bound dispatch function. | |
const dispatch = store.dispatch.bind(store) | |
// Update on state changes. | |
const performUpdate = () => update(store.getState()) | |
// Subscribe to store on mount, and do unsubscribe on unmount. | |
useEffect(() => store.subscribe(performUpdate), []) | |
// Get mapped state and dispatchers. | |
const state = typeof mapState === 'function' ? mapState(store.getState(), props) : {} | |
const dispatchers = typeof mapDispatch === 'function' ? mapDispatch(dispatch) : {} | |
// Apply state and dispatchers to wrapped component and render. | |
return <WrappedComponent {...props} {...state} {...dispatchers} /> | |
} | |
/*** Store Provider *** | |
import { StoreProvider } from './micro-react-redux' // this gist | |
import createStore from './micro-redux' // see micro-redux gist | |
import reducer from './reducer' // create your own reducer | |
const App = () => <MyComponentTree /> | |
const store = createStore(reducer) | |
export default () => ( | |
<StoreProvider store={store}><App /></StoreProvider> | |
) | |
*/ | |
/*** connect *** | |
const SomeComponent = (props) => { | |
return <MyComponent {...} /> | |
} | |
function mapState(state) { | |
return {...} | |
} | |
function mapDispatch(dispatch) { | |
return {...} | |
} | |
export default connect(mapState, mapDispatch)(SomeComponent) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment