Instantly share code, notes, and snippets.
Save gaearon/1d19088790e70ac32ea636c025ba424e to your computer and use it in GitHub Desktop.
| // connect() is a function that injects Redux-related props into your component. | |
| // You can inject data and callbacks that change that data by dispatching actions. | |
| functionconnect(mapStateToProps,mapDispatchToProps){ | |
| // It lets us inject component as the last step so people can use it as a decorator. | |
| // Generally you don't need to worry about it. | |
| returnfunction(WrappedComponent){ | |
| // It returns a component | |
| returnclassextendsReact.Component{ | |
| render(){ | |
| return( | |
| // that renders your component | |
| <WrappedComponent | |
| {/* with its props */} | |
| {...this.props} | |
| {/* and additional props calculated from Redux store */} | |
| {...mapStateToProps(store.getState(),this.props)} | |
| {...mapDispatchToProps(store.dispatch,this.props)} | |
| /> | |
| ) | |
| } | |
| componentDidMount(){ | |
| // it remembers to subscribe to the store so it doesn't miss updates | |
| this.unsubscribe=store.subscribe(this.handleChange.bind(this)) | |
| } | |
| componentWillUnmount(){ | |
| // and unsubscribe later | |
| this.unsubscribe() | |
| } | |
| handleChange(){ | |
| // and whenever the store state changes, it re-renders. | |
| this.forceUpdate() | |
| } | |
| } | |
| } | |
| } | |
| // This is not the real implementation but a mental model. | |
| // It skips the question of where we get the "store" from (answer: <Provider> puts it in React context) | |
| // and it skips any performance optimizations (real connect() makes sure we don't re-render in vain). | |
| // The purpose of connect() is that you don't have to think about | |
| // subscribing to the store or perf optimizations yourself, and | |
| // instead you can specify how to get props based on Redux store state: | |
| constConnectedCounter=connect( | |
| // Given Redux state, return props | |
| state=>({ | |
| value:state.counter, | |
| }), | |
| // Given Redux dispatch, return callback props | |
| dispatch=>({ | |
| onIncrement(){ | |
| dispatch({type:'INCREMENT'}) | |
| } | |
| }) | |
| )(Counter) |
eqyiel commentedJan 6, 2017
@therewillbecode seehttp://redux.js.org/docs/api/Store.html#subscribe
To unsubscribe the change listener, invoke the function returned by subscribe.
nonnontrivial commentedFeb 11, 2017
Super clear and helpful. Thanks :)
ghost commentedApr 22, 2017
Thank you! Pseudo-implementations help my mental model tons.
iroy2000 commentedJun 7, 2017
Thanks a lot, it makes understanding the redux implementation much easier 👍
andersonferrari commentedJul 27, 2017
great explanation!!! thanks!!!
esafirm commentedAug 18, 2017
Wow this is great 👍
gulshanzealous commentedSep 6, 2017
Aha moment ! Concise and powerful : terms we hardly associate together with libraries.
karltaylor commentedSep 13, 2017
👍
dvvtms commentedSep 20, 2017
here is my decorator to simplify things:
importReactfrom"react";import{bindActionCreators}from"redux";import{connect}from"react-redux";import*asactionsfrom"./actions";constdecorator=ComponentToDecorate=>{classComponentDecoratedextendsReact.Component{render(){const{ authState, authActions, ...rest}=this.props;return(<ComponentToDecorateauth={{state:authState,actions:authActions}}{...rest}/>);}}returnconnect(state=>({authState:state.services.auth.authentication}),dispatch=>({authActions:bindActionCreators(actions,dispatch)}))(ComponentDecorated);};exportdefaultdecorator;
i use it in some complicated components. is there is anything wrong with this?
kinotto commentedOct 11, 2017
fantastic! clear and concise, thanks@gaearon
anotherxx commentedOct 31, 2017
Thank you,very clear explanation,like you methods to educate.
Especially , you approach when you explain how things work under the hood!
vitali-zaneuski commentedMay 5, 2018
Good and brief explanation
Bosn commentedMay 18, 2018
Fantastic work!
ashinzekene commentedJun 9, 2018
Can this be used in prod?
sibelius commentedOct 31, 2018
Hooks?
afrazahmad21 commentedNov 13, 2018
So connect actually returns a new component hah !!! thanks for this snippet
demukeshchouhan commentedDec 6, 2018
If I use this syntax.
const mapState = ({ state }) => ({ ...state });
- The component will be heavy?
- The component will be re-render every time store change?
- The component will take extra memory to store props?
- Or it's just a syntactic sugar?
farazh commentedJan 17, 2019
Great Explanation!
dinukadev commentedFeb 21, 2019
This helped. Thank you!
ezmiller commentedMar 4, 2019
Is it accurate to say thatconnect implements some variant of the observer pattern? If yes or no (or kinda), why?
kas-elvirov commentedJan 10, 2020
@ezmiller i would say -connect() is an observer for sure. Why? Go tothe internet
cyogian commentedFeb 20, 2020
I just came here to see how a HOC works in practical. Thanks for this explaination.
aakashtyg commentedMar 15, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@gaearon don't you think the subscription logic should be in theconstructor and notcomponentDidMount? If I am dispatching an action fromWrappedComponent'scomponentDidMount. We won't see the updated state (it wont re render) inWrappedComponent, sincecomponentDidMount of theWrappedComponent will run first before the subscription happens incomponentDidMount insideconnect()
VitaminCtea commentedApr 15, 2020
Very clear explanation! 👍
gideonmensadappah commentedApr 16, 2020
Thank You That was a clear explanation !!
4nkitpatel commentedJul 13, 2020
Thanks, this mental model helping me a lot while learning react with redux :)
jaiho8816 commentedNov 10, 2021
thanks@gaearon
nguyenyou commentedNov 11, 2021
Thank you 🚀🚀🚀
farhadibehnamdev commentedJun 13, 2022
Thank you so much. It was so helpful.
Brinezera commentedMar 25, 2024
thanks!