Skip to content

Instantly share code, notes, and snippets.

@gianmarcotoso
Last active April 9, 2018 09:50
Show Gist options
  • Save gianmarcotoso/79dd91f2bdbce9be222c9968ca0a68ed to your computer and use it in GitHub Desktop.
Save gianmarcotoso/79dd91f2bdbce9be222c9968ca0a68ed to your computer and use it in GitHub Desktop.
Connect React to Redux with Context API
import * as React from 'react'
import { Store, Unsubscribe, Dispatch } from 'redux'
const stateContext = React.createContext()
const { Provider, Consumer } = stateContext
export interface StateProviderProps<T> {
store: Store<T>
}
export interface ConnectProps<T, S> {
select?: (state: T) => S | any
children: (slicedState: S, dispatch: Dispatch<any>) => React.ReactNode
}
export class StateProvider<T> extends React.Component<StateProviderProps<T>, { reduxState: T } > {
state = { reduxState: this.props.store && this.props.store.getState() }
private unsubscribe: Unsubscribe
constructor(props) {
super(props)
if (!props.store) {
throw new Error('Store has not been provided to the StateProvider')
}
this.unsubscribe = this.props.store.subscribe(() => {
this.setState({ reduxState: this.props.store.getState() })
})
}
componentWillUnmount() {
this.unsubscribe()
}
render() {
return (
<Provider value={{state: this.state.reduxState, dispatch: this.props.store.dispatch}}>
{this.props.children}
</Provider>
)
}
}
export class Connect<T = any, S = any> extends React.Component<ConnectProps<T, S>> {
render() {
const select = this.props.select || (s => s)
const render = this.props.children
return <Consumer>{storeContext => render(select(storeContext.state), storeContext.dispatch)}</Consumer>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment