Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
connect.js explained
// 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)
@aweary

This comment has been minimized.

Copy link

@aweary aweary commented May 17, 2016

Alright, now React next! 😄

@philipstanislaus

This comment has been minimized.

Copy link

@philipstanislaus philipstanislaus commented Oct 4, 2016

Thanks for the explanation, @gaearon! Might it be possible that you talk a bit about the performance optimizations in the connect function? Thanks!

@therewillbecode

This comment has been minimized.

Copy link

@therewillbecode therewillbecode commented Dec 12, 2016

Really useful example. Thanks so much.

Why is the unsubscribe method of the decorated component being called here in componentDidMount?
I am confused as the comment says:

it remembers to subscribe to the store so it doesn't miss updates

@eqyiel

This comment has been minimized.

Copy link

@eqyiel eqyiel commented Jan 6, 2017

@therewillbecode see http://redux.js.org/docs/api/Store.html#subscribe

To unsubscribe the change listener, invoke the function returned by subscribe.

@nonnontrivial

This comment has been minimized.

Copy link

@nonnontrivial nonnontrivial commented Feb 11, 2017

Super clear and helpful. Thanks :)

@Dianna

This comment has been minimized.

Copy link

@Dianna Dianna commented Apr 22, 2017

Thank you! Pseudo-implementations help my mental model tons.

@iroy2000

This comment has been minimized.

Copy link

@iroy2000 iroy2000 commented Jun 7, 2017

Thanks a lot, it makes understanding the redux implementation much easier 👍

@andersonferrari

This comment has been minimized.

Copy link

@andersonferrari andersonferrari commented Jul 27, 2017

great explanation!!! thanks!!!

@esafirm

This comment has been minimized.

Copy link

@esafirm esafirm commented Aug 18, 2017

Wow this is great 👍

@gulshanzealous

This comment has been minimized.

Copy link

@gulshanzealous gulshanzealous commented Sep 6, 2017

Aha moment ! Concise and powerful : terms we hardly associate together with libraries.

@karltaylor

This comment has been minimized.

Copy link

@karltaylor karltaylor commented Sep 13, 2017

👍

@dvvtms

This comment has been minimized.

Copy link

@dvvtms dvvtms commented Sep 20, 2017

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?

@kinotto

This comment has been minimized.

Copy link

@kinotto kinotto commented Oct 11, 2017

fantastic! clear and concise, thanks @gaearon

@Nerhbest

This comment has been minimized.

Copy link

@Nerhbest Nerhbest commented Oct 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

This comment has been minimized.

Copy link

@vitali-zaneuski vitali-zaneuski commented May 5, 2018

Good and brief explanation

@Bosn

This comment has been minimized.

Copy link

@Bosn Bosn commented May 18, 2018

Fantastic work!

@ashinzekene

This comment has been minimized.

Copy link

@ashinzekene ashinzekene commented Jun 9, 2018

Can this be used in prod?

@sibelius

This comment has been minimized.

Copy link

@sibelius sibelius commented Oct 31, 2018

Hooks?

@afrazahmad21

This comment has been minimized.

Copy link

@afrazahmad21 afrazahmad21 commented Nov 13, 2018

So connect actually returns a new component hah !!! thanks for this snippet

@demukeshchouhan

This comment has been minimized.

Copy link

@demukeshchouhan demukeshchouhan commented Dec 6, 2018

If I use this syntax.

const mapState = ({ state }) => ({ ...state });

  1. The component will be heavy?
  2. The component will be re-render every time store change?
  3. The component will take extra memory to store props?
  4. Or it's just a syntactic sugar?
@farazh

This comment has been minimized.

Copy link

@farazh farazh commented Jan 17, 2019

Great Explanation!

@dinukadev

This comment has been minimized.

Copy link

@dinukadev dinukadev commented Feb 21, 2019

This helped. Thank you!

@ezmiller

This comment has been minimized.

Copy link

@ezmiller ezmiller commented Mar 4, 2019

Is it accurate to say that connect implements some variant of the observer pattern? If yes or no (or kinda), why?

@artem-solovev

This comment has been minimized.

Copy link

@artem-solovev artem-solovev commented Jan 10, 2020

@ezmiller i would say - connect() is an observer for sure. Why? Go to the internet

@cyogian

This comment has been minimized.

Copy link

@cyogian cyogian commented Feb 20, 2020

I just came here to see how a HOC works in practical. Thanks for this explaination.

@aakash-cr7

This comment has been minimized.

Copy link

@aakash-cr7 aakash-cr7 commented Mar 15, 2020

@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()

@VitaminCtea

This comment has been minimized.

Copy link

@VitaminCtea VitaminCtea commented Apr 15, 2020

Very clear explanation! 👍

@gideonmensadappah

This comment has been minimized.

Copy link

@gideonmensadappah gideonmensadappah commented Apr 16, 2020

Thank You That was a clear explanation !!

@4nkitpatel

This comment has been minimized.

Copy link

@4nkitpatel 4nkitpatel commented Jul 13, 2020

Thanks, this mental model helping me a lot while learning react with redux :)

@prajapati-parth

This comment has been minimized.

Copy link

@prajapati-parth prajapati-parth commented Jul 26, 2020

@gaearon when connecting a component and using redux-thunk, dispatching twice would update the state twice. Would that mean that connected components would re-render twice (considering that the changes in state are something that would cause a re-render if used with component's native state)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.