-
Star
(710)
You must be signed in to star a gist -
Fork
(80)
You must be signed in to fork a gist
-
-
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. | |
| function connect(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. | |
| return function (WrappedComponent) { | |
| // It returns a component | |
| return class extends React.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: | |
| const ConnectedCounter = connect( | |
| // Given Redux state, return props | |
| state => ({ | |
| value: state.counter, | |
| }), | |
| // Given Redux dispatch, return callback props | |
| dispatch => ({ | |
| onIncrement() { | |
| dispatch({ type: 'INCREMENT' }) | |
| } | |
| }) | |
| )(Counter) |
Super clear and helpful. Thanks :)
Thank you! Pseudo-implementations help my mental model tons.
Thanks a lot, it makes understanding the redux implementation much easier π
great explanation!!! thanks!!!
Wow this is great π
Aha moment ! Concise and powerful : terms we hardly associate together with libraries.
π
here is my decorator to simplify things:
import React from "react";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import * as actions from "./actions";
const decorator = ComponentToDecorate => {
class ComponentDecorated extends React.Component {
render() {
const { authState, authActions, ...rest } = this.props;
return (
<ComponentToDecorate auth={{ state: authState, actions: authActions }}
{...rest}
/>
);
}
}
return connect(
state => ({
authState: state.services.auth.authentication
}),
dispatch => ({
authActions: bindActionCreators(actions, dispatch)
})
)(ComponentDecorated);
};
export default decorator;i use it in some complicated components. is there is anything wrong with this?
fantastic! clear and concise, thanks @gaearon
Thank you,very clear explanation,like you methods to educate.
Especially , you approach when you explain how things work under the hood!
Good and brief explanation
Fantastic work!
Can this be used in prod?
Hooks?
So connect actually returns a new component hah !!! thanks for this snippet
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?
Great Explanation!
This helped. Thank you!
Is it accurate to say that connect implements some variant of the observer pattern? If yes or no (or kinda), why?
@ezmiller i would say - connect() is an observer for sure. Why? Go to the internet
I just came here to see how a HOC works in practical. Thanks for this explaination.
@gaearon don't you think the subscription logic should be in the constructor and not componentDidMount? If I am dispatching an action from WrappedComponent's componentDidMount. We won't see the updated state (it wont re render) in WrappedComponent, since componentDidMount of the WrappedComponent will run first before the subscription happens in componentDidMount inside connect()
Very clear explanation! π
Thank You That was a clear explanation !!
Thanks, this mental model helping me a lot while learning react with redux :)
thanks @gaearon
Thank you πππ
Thank you so much. It was so helpful.
thanks!
@therewillbecode see http://redux.js.org/docs/api/Store.html#subscribe