React-Redux connect(): when and how to use it
Tags: webdev, programming, javascript, react
Published: 2018-09-21 12:15:39

---
title: React-Redux connect(): when and how to use it
published: true
tags: web-development,programming,javascript,react
canonical_url: https://blog.logrocket.com/react-redux-connect-when-and-how-to-use-it-f2a1edab2013
---

#### Learn how to create container components in React that are connected to the Redux state.

![](https://cdn-images-1.medium.com/max/1024/1*NUNUmFiNcqYH3hjNjgB70g.jpeg)

React provides two major mechanisms for providing data to components namely: **props** and **state**. While _props_ are read-only and allow a parent component to pass attributes to a child component, _state_ is local and encapsulated within the component and can change at any time in the component’s lifecycle.

Since _state_ is a very powerful mechanism for building powerful and dynamic React apps, it becomes necessary that state is properly managed in the application. Several libraries already exist, that provide a well-structured architecture for managing application state such as [**Flux**](https://facebook.github.io/flux), [**Redux**](https://redux.js.org/), [**MobX**](https://mobx.js.org/).

**Redux** is a predictable state container for JavaScript apps ranging from vanilla apps to framework apps. It has a very tiny footprint and yet allows you to write consistent apps that can run in any environment:

![](https://cdn-images-1.medium.com/max/1008/0*rkzzibjBKN8nV_EY.png)<figcaption>Simple Redux Store</figcaption>

_This guide is based on state management in React applications with Redux using_ [**_react-redux_**](https://github.com/reduxjs/react-redux)_. It is not an introduction to either React or Redux._

_It assumes you already have a fundamental understanding of React and the Redux architecture and API. If that’s not the case then you can check the React documentation_ [_here_](https://reactjs.org/docs/) _and the Redux documentation_ [_here_](https://redux.js.org/)_._

### React-Redux

The **react-redux** package provides React bindings for the Redux state container making it very easy for a React application to be connected to a Redux store. This allows you to separate your React application components based on their connection to the Redux store as follows:

1. **Presentational Components**  — These components are only concerned with how things look and are not aware of the Redux state. They get their data from props and may trigger callbacks passed to them via props.
2. **Container Components**  — These components are responsible for how things work and are fully aware of the Redux state. They are often created using React Redux and may dispatch Redux actions. They also subscribe to changes in the Redux state.

You can learn more about this separation of concerns from this [article](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). In this guide, our major focus will be on container components that are connected to the Redux state using **react-redux**.

[![](https://cdn-images-1.medium.com/max/1024/1*GPjaPKNNUYHU8EsA3Z0JGA.png)](https://logrocket.com/signup/)

The **react-redux** package exposes a very simple interface, and all you should be interested in is just the following:

1. **<Provider store>**  — Wraps the React application and makes the Redux state available to all container components in the application’s hierarchy
2. **connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])** — Creates a higher-order component for making container components out of base React components

You can install **react-redux** in your project as follows:

```jsx
npm install react-redux --save
```

Given that you already have a Redux store setup for your React application, here is how you can connect the app to the Redux store:
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import createStore from './createReduxStore';

const store = createStore();
const rootElement = document.getElementById('root');

ReactDOM.render((
  <Provider store={store}>
    <AppRootComponent />
  </Provider>
), rootElement);
```
With this setup, you can now create container components, that are connected to the Redux store, within the hierarchy of the **AppRootComponent** using the **connect()** API.

### When to use connect()

#### 1. Creating container components.

As stated in the previous section, the **react-redux** **connect()** API is used for creating container elements that are connected to the Redux store. The Redux store to be connected to is derived from the topmost ancestor of the component using the React context mechanism. You have no need for **connect()** if you are only creating a presentational component.

Whether you want to just get data from the Redux store, or you want to dispatch actions on the Redux store, or you want to do both in your React component, you can make the component a container component by wrapping it in a higher-order component returned by **react-redux** **connect()**:
```jsx
import React from 'react';
import { connect } from 'react-redux';
import Profile from './components/Profile';

function ProfileContainer(props) {
  return (
    props.loggedIn
      ? <Profile profile={props.profile} />
      : <div>Please login to view profile.</div>
  )
}

const mapStateToProps = function(state) {
  return {
    profile: state.user.profile,
    loggedIn: state.auth.loggedIn
  }
}

export default connect(mapStateToProps)(ProfileContainer);
```
#### 2. Avoiding manual subscription to the Redux store.

You could create a container component yourself and manually subscribe the component to the Redux store using **store.subscribe()**. However, using **react-redux** **connect()** comes with some performance improvements and optimizations which you may not be able to implement in your application.

In the following code snippet, we attempt to manually create a container component and connect it to the Redux store by subscribing to the store, in order to achieve a similar functionality as with the previous code snippet:
```jsx
import React, { Component } from 'react';
import store from './reduxStore';
import Profile from './components/Profile';

class ProfileContainer extends Component {

  state = this.getCurrentStateFromStore()
  
  getCurrentStateFromStore() {
    return {
      profile: store.getState().user.profile,
      loggedIn: store.getState().auth.loggedIn
    }
  }
  
  updateStateFromStore = () => {
    const currentState = this.getCurrentStateFromStore();
    
    if (this.state !== currentState) {
      this.setState(currentState);
    }
  }
  
  componentDidMount() {
    this.unsubscribeStore = store.subscribe(this.updateStateFromStore);
  }
  
  componentWillUnmount() {
    this.unsubscribeStore();
  }
  
  render() {
    const { loggedIn, profile } = this.state;
    
    return (
      loggedIn
        ? <Profile profile={profile} />
        : <div>Please login to view profile.</div>
    )
  }
  
}

export default ProfileContainer;
```
**react-redux** **connect()** also provides additional flexibility, allowing you to configure container components to receive dynamic props based on the props initially passed to them. This is useful for selecting a slice of the Redux state based on props, or to bind action creators to a particular variable from props.

If your React application uses multiple Redux stores, **react-redux** **connect()** allows you to easily specify which store a container component should be connected to.

### Anatomy of connect()

The **connect()** function provided by **react-redux** can take up to four arguments, all of which are _optional_. Calling the **connect()** function returns a _higher-order component_ which can be used to wrap any React component.

Since a higher-order component is returned by **connect()**, it has to be invoked again with the base React component in order to convert it to a container component:

```jsx
const ContainerComponent = connect()(BaseComponent);
```

Here is the signature of the **connect()** function:

```jsx
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
```

#### mapStateToProps(state, [ownProps]) => stateProps

This argument is a **function** that returns either a **plain object** or **another function**. Passing this argument subscribes the container component to the Redux store updates, which means that the **mapStateToProps** function will be invoked each time the store updates. If you are not interested in store updates, leave it as **undefined** or  **null**.

**mapStateToProps** is declared with **two parameters** , the second one being _optional_. The first parameter is the current state of the Redux store. The second parameter, if passed, is an object of the props passed to the component:
```jsx
const mapStateToProps = function(state) {
  return {
    profile: state.user.profile,
    loggedIn: state.auth.loggedIn
  }
}

export default connect(mapStateToProps)(ProfileComponent);
```
If a plain object is returned from **mapStateToProps** , the returned **stateProps** object is merged into the component’s props. You can access these props in the component as follows:
```jsx
function ProfileComponent(props) {
  return (
    props.loggedIn
      ? <Profile profile={props.profile} />
      : <div>Please login to view profile.</div>
  )
}
```
However, if a function is returned, that function is used as **mapStateToProps** for each instance of the component. This can be useful for improving the rendering performance and for memoization.

#### mapDispatchToProps(dispatch, [ownProps]) => dispatchProps

This argument can either be an **object** or a **function** that returns either a **plain object** or **another function**. To better illustrate how **mapDispatchToProps** works, you will need to have some action creators.

For example, say you have the following action creators:
```jsx
export const writeComment = (comment) => ({
  comment,
  type: 'WRITE_COMMENT'
});

export const updateComment = (id, comment) => ({
  id,
  comment,
  type: 'UPDATE_COMMENT'
});

export const deleteComment = (id) => ({
  id,
  type: 'DELETE_COMMENT'
});
```
**1. Default Implementation**

If you don’t supply your own **mapDispatchToProps** object or function, the default implementation will be used, which simply injects the store’s **dispatch** method as a prop to the component.

You can use the **dispatch** prop in your component as follows:
```jsx
import React from 'react';
import { connect } from 'react-redux';
import { updateComment, deleteComment } from './actions';

function Comment(props) {
  const { id, content } = props.comment;
  
  // Invoking the actions via props.dispatch()
  const editComment = () => props.dispatch(updateComment(id, content));
  const removeComment = () => props.dispatch(deleteComment(id));
  
  return (
    <div>
      <p>{ content }</p>
      <button type="button" onClick={editComment}>Edit Comment</button>
      <button type="button" onClick={removeComment}>Remove Comment</button>
    </div>
  )
}

export default connect()(Comment);
```
**2. Passing an object**

If an **object** is passed for this argument, each function in the object will be taken to be a Redux action creator and will be wrapped into a call to the store’s **dispatch** method so that it can be called directly. The resulting **dispatchProps** object of action creators will be merged into the component’s props.

The following code snippet shows how you can define **mapDispatchToProps** by supplying an object of action creators, and how the action creators can be used as props to your React component:
```jsx
import React from 'react';
import { connect } from 'react-redux';
import { updateComment, deleteComment } from './actions';

function Comment(props) {
  const { id, content } = props.comment;
  
  // Invoking the actions directly as component props
  const editComment = () => props.updatePostComment(id, content);
  const removeComment = () => props.deletePostComment(id);
  
  return (
    <div>
      <p>{ content }</p>
      <button type="button" onClick={editComment}>Edit Comment</button>
      <button type="button" onClick={removeComment}>Remove Comment</button>
    </div>
  )
}

// Object of action creators
const mapDispatchToProps = {
  updatePostComment: updateComment,
  deletePostComment: deleteComment
}

export default connect(null, mapDispatchToProps)(Comment);
```
**3. Passing a function**

If a **function** is passed, it is left to you to return an object of **dispatchProps** that binds action creators using the store’s **dispatch** method. The function takes the store’s **dispatch** as its first parameter. As with **mapStateToProps** , it can also take an _optional_ **ownProps** second parameter that maps to the original props passed to the component.

If this function returns another function, then the returned function is used as **mapDispatchToProps** instead, which can be useful for improving rendering performance and memoization.

The **bindActionCreators()** helper provided by Redux can be used within this function to bind action creators to the store’s **dispatch**  method.

The following code snippet shows how you can define **mapDispatchToProps** by supplying a function, and how the **bindActionCreators()** helper can be used to bind the comment action creators to a React component’s **props.actions** :
```jsx
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as commentActions from './actions';

function Comment(props) {
  const { id, content } = props.comment;
  const { updateComment, deleteComment } = props.actions;
  
  // Invoking the actions from props.actions
  const editComment = () => updateComment(id, content);
  const removeComment = () => deleteComment(id);
  
  return (
    <div>
      <p>{ content }</p>
      <button type="button" onClick={editComment}>Edit Comment</button>
      <button type="button" onClick={removeComment}>Remove Comment</button>
    </div>
  )
}

const mapDispatchToProps = (dispatch) => {
  return {
    actions: bindActionCreators(commentActions, dispatch)
  }
}

export default connect(null, mapDispatchToProps)(Comment);
```
#### mergeProps(stateProps, dispatchProps, ownProps) => props

This argument, if passed, is a **function** that takes **three parameters ** — namely:

- **`stateProps`**  — the props object returned from a call to **`mapStateToProps()`**

- **`dispatchProps`**  — the action creators props object from **`mapDispatchToProps()`**

- **`ownProps`** — the original props received by the component.

This function returns a plain object of props that will be passed to the wrapped component. This is useful for conditionally mapping part of the Redux store’s state or action creators based on props.

When this function is not supplied, the default implementation is as follows:
```jsx
const mergeProps = (stateProps, dispatchProps, ownProps) => {
  return Object.assign({}, ownProps, stateProps, dispatchProps)
}
```
#### options

The options object, if specified, contains options for modifying the behavior of **connect()**. **connect()** is a special implementation of **connectAdvanced()**, it accepts most of the options available to **connectAdvanced()** with some additional options.

You can refer to [this documentation](https://github.com/reduxjs/react-redux/blob/master/docs/api.md) to see all the options available to **connect()** and how they can modify its behavior.

### How to use connect()

#### Setting the store

Before converting a regular React component to a container component using **connect()**, you have to specify the Redux store the component will be connected to.

Assume that you have a container component named **NewComment** for adding a new comment to a post and also showing a button to submit the comment. The component might look like the following code snippet:
```jsx
import React from 'react';
import { connect } from 'react-redux';

class NewComment extends React.Component {

  input = null
  
  writeComment = evt => {
    evt.preventDefault();
    const comment = this.input.value;
    
    comment && this.props.dispatch({ type: 'WRITE_COMMENT', comment });
  }
  
  render() {
    const { id, content } = this.props.comment;
    
    return (
      <div>
        <input type="text" ref={e => this.input = e} placeholder="Write a comment" />
        <button type="button" onClick={this.writeComment}>Submit Comment</button>
      </div>
    )
  }
  
}

export default connect()(NewComment);
```
For you to actually use this component in your application, you will have to specify the Redux store the component must be connected to, otherwise, you will get an error.

This can be done in two ways:

**1. Set the store prop on the container component**

The first way is to specify the Redux store on the component by passing a reference to the Redux store as the value of the **store** prop of the component:
```jsx
import React from 'react';
import store from './reduxStore';
import NewComment from './components/NewComment';

function CommentsApp(props) {
  return <NewComment store={store} />
}
```
**2. Set the store prop on a `<Provider>` component**

If you wish to set the Redux store once for your application, then this is the way to go. This is usually the case for apps that use only one Redux store.

**react-redux** provides a **`<Provider>`** component which can be used to wrap the root application component. It accepts a **store** prop which expects a reference to the Redux store you want to use for your application. The **store** is passed down to container components down the app’s hierarchy using React’s context mechanism:
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import store from './reduxStore';
import { Provider } from 'react-redux';
import NewComment from './components/NewComment';

function CommentsApp(props) {
  return <NewComment />
}

ReactDOM.render((
  <Provider store={store}>
    <CommentsApp />
  </Provider>
), document.getElementById('root'))
```
#### Accessing ownProps

As stated earlier, the **mapStateToProps** and **mapDispatchToProps** functions passed to **connect()** can be declared with the **ownProps** of the component as the second parameter.

However, there is a **caveat**. If the number of mandatory parameters of the declared function is less than **2** , then **ownProps** will never be passed. But if the function is declared with no mandatory parameters or at least **2** parameters, then **ownProps** is passed.

Here are a few scenarios:

**1. Declared with no parameters**
```jsx
const mapStateToProps = function() {
  console.log(arguments[0]); // state
  console.log(arguments[1]); // ownProps
};
```
Here, **ownProps** is passed because the function is declared with no mandatory parameters. Hence, the following will also work in a similar fashion, using the new ES6 rest parameters syntax:
```jsx
const mapStateToProps = function(...args) {
  console.log(args[0]); // state
  console.log(args[1]); // ownProps
};
```
**2. Declared with one parameter**
```jsx
const mapStateToProps = function(state) {
  console.log(state); // state
  console.log(arguments[1]); // undefined
};
```
Here, there is only one parameter, **state**. Hence, **arguments[1]** is **undefined** because **ownProps** is not passed.

**3. Declared with default parameter**
```jsx
const mapStateToProps = function(state, ownProps = {}) {
  console.log(state); // state
  console.log(ownProps); // {}
};
```
Here, there is only one mandatory parameter, **state** , because the second **ownProps** parameter is _optional_ since a default value has been specified for it. Hence, since there is only one mandatory parameter, **ownProps** is not passed and as a result it maps to the default value that was assigned to it - `{}`.

**4. Declared with two parameters**
```jsx
const mapStateToProps = function(state, ownProps) {
  console.log(state); // state
  console.log(ownProps); // ownProps
};
```
This is pretty straightforward. **ownProps** is passed here since the function is declared with two mandatory parameters.

### Conclusion

In this guide, you have seen when and how to use the **connect()** API provided by the **react-redux** package to create container components that are connected to the Redux state.

While this guide, covers much of the anatomy of the **connect()** API and its usage, it did not extensively show use case examples. You can find more of these in [this documentation](https://github.com/reduxjs/react-redux/blob/master/docs/api.md).

#### Clap & Follow

If you found this article insightful, feel free to give some rounds of applause if you don’t mind.

You can also follow me on Medium ([Glad Chinda](https://medium.com/u/ddcd0e9719e5)) for more insightful articles you may find helpful. You can also follow me on Twitter ([@gladchinda](https://twitter.com/@gladchinda)).

**_Enjoy coding…_**
* * *
## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [React Redux Connect Tutorial - When and how to use it](https://blog.logrocket.com/react-redux-connect-when-and-how-to-use-it-f2a1edab2013/) appeared first on [LogRocket Blog](https://blog.logrocket.com).