Skip to content

Instantly share code, notes, and snippets.

@khrykin
Created January 22, 2018 14:13
Show Gist options
  • Save khrykin/ebcac362a260fb5c6adacfb38fce2921 to your computer and use it in GitHub Desktop.
Save khrykin/ebcac362a260fb5c6adacfb38fce2921 to your computer and use it in GitHub Desktop.
Connect local redux store to a component
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