Created
January 22, 2018 14:13
-
-
Save khrykin/ebcac362a260fb5c6adacfb38fce2921 to your computer and use it in GitHub Desktop.
Connect local redux store to a component
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
import React, { Component } from 'react' | |
import hoistNonReactStatic from 'hoist-non-react-statics' | |
import { createStore, bindActionCreators } from 'redux' | |
/** | |
* This is a HOC that attaches its own redux store to a component - | |
* the store lives and dies with the component. | |
* | |
* Usecase: | |
* When you don't feel comfortable with this.setState(), but | |
* don't want to persist this component's state in global state either. | |
* | |
* Features: | |
* - Redux store and therefore all actions are scoped to the connected component | |
* instance. | |
* - Component updates on every store state change. | |
* - Store state is merged with component's own props and mapDispatchToProps. | |
* - mapDispatchToProps and mergeProps has `react-redux`-like API | |
* - There is no way for connected component's children to get store state, | |
* other than from props. | |
* | |
* Usage: | |
* const WithStoreCompoennt = connectLocalStore(...createStoreArgs)( | |
* mapDispatchToProps, | |
* mergeProps, | |
* ) | |
* (Component) | |
* | |
*/ | |
export default function connectLocalStore(...createStoreArgs) { | |
return ( | |
mapDispatchToProps = {}, | |
mergeProps = (stateProps, dispatchProps, ownProps) => | |
Object.assign({}, ownProps, stateProps, dispatchProps) | |
) => { | |
return WrappedComponent => { | |
const ConnectLocalStoreComponent = class extends Component { | |
constructor(props) { | |
super(props) | |
this.store = createStore(...createStoreArgs) | |
if (!mapDispatchToProps) { | |
this.actionCreators = { dispatch: this.store.dispatch } | |
} else { | |
this.actionCreators = | |
typeof mapDispatchToProps === 'function' | |
? mapDispatchToProps(this.store.dispatch, props) | |
: bindActionCreators(mapDispatchToProps, this.store.dispatch) | |
} | |
this.store.subscribe(() => { | |
const storeState = this.store.getState() | |
this.setState({ storeState }) | |
}) | |
this.state = { storeState: this.store.getState() } | |
} | |
getProps = () => { | |
return mergeProps( | |
this.state.storeState, | |
this.actionCreators, | |
this.props | |
) | |
} | |
render() { | |
return <WrappedComponent {...this.getProps()} /> | |
} | |
} | |
hoistNonReactStatic(ConnectLocalStoreComponent, WrappedComponent) | |
ConnectLocalStoreComponent.displayName = `ConnectLocalStore(${getDisplayName( | |
WrappedComponent | |
)})` | |
return ConnectLocalStoreComponent | |
} | |
} | |
} | |
function getDisplayName(WrappedComponent) { | |
return WrappedComponent.displayName || WrappedComponent.name || 'Component' | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment