Author avatar

Gaurav Singhal

Use the connect() Function to Pass Redux State to Sub-routes

Gaurav Singhal

  • Oct 16, 2020
  • 7 Min read
  • 14 Views
  • Oct 16, 2020
  • 7 Min read
  • 14 Views
Web Development
Front End Web Development
Client-side Frameworks
React

Introduction

React uses a component state that can be modified into the component and pass it to the child component as it gets connected to the parent. Still, this state is not sufficient to manage the state if components are not interrelated.

Redux is a library that allows a React app to create a global state object that can be used in any component across the app by consuming the state object. A Redux state is a standalone object managed globally in the React app. Thus, every route and sub-route should be able to access the global state piece, which is possible using the connect() method. This guide will demonstrate how any app sub-route can access the Redux state.

Create Redux State with Store

Before any component, access the Redux state object. The first step is to create the store that will represent the combined state object used by the various components in the React app.

Two libraries need to get installed to configure the store and routes.

1
2
npm install react-redux
npm install react-router-dom
shell

Then, configure the router along with the route.

1
import { Route, Switch,  BrowserRouter as Router } from 'react-router-dom';
jsx

After importing the router, you need to configure various routes related to your components.

1
2
3
4
5
6
7
8
9
10
11
12
13
class AppRoutes extends React.Component {
    render() {
        return (
            <Switch>
                <Route exact path={'/'} component={Home} />
                <Route path={'/screen1'} component={Screen1} />
                <Route path={'/screen2'} component={Screen2} />
                <Route path={'/screen3'} component={Screen3} />
                <Route component={NotFoundPage} />
            </Switch>
        );
    }
}
jsx

Based on the routes, if any component wants to access the Redux state, the store needs to be configured. Below is the code to create the store.

1
2
3
4
// To use createStore function
import { createStore } from 'redux';

const store = createStore(contactApp);
jsx

The store then is assigned to the <Provider>, which allows any component to access the global state object.

1
2
3
4
5
6
7
8
9
<Provider store={store}>
    <Switch>
        <Route exact path={'/'} component={Home} />
        <Route path={'/screen1'} component={Screen1} />
        <Route path={'/screen2'} component={Screen2} />
        <Route path={'/screen3'} component={Screen3} />
        <Route component={NotFoundPage} />
    </Switch>
</Provider>
jsx

The provider has one property called store that defines the store and makes Redux states available across the app. Your app is configured to access the Redux state object by implementing a router along with the Redux store. Now you can access any piece of state using the connect() function.

Accessing Redux State to the Sub-routes

After configuring the store with the provider you can access the state object, but it can be done directly; hence, the Redux's additional functionality gets used.

React Redux has one additional feature called connect() that allows you to connect your React component with the Redux store. The connect() function has four different props:

  • mapStateToProps
  • mapDispatchToProps
  • mergeProps
  • options

You can use the props mapStateToProps to extract the global state and use it into the existing component. For example, one form adds the contact and another component, which shows the contact list; hence, the form component is a parent, and the list component is a child component.

App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
render() {
    return (
      <>
        <h1>CONTACT APP</h1>
        <section>
          <section>
            <input
              type="text"
              name="message"
              placeholder="Name"
              value={this.state.inputs.message}
              onChange={this.onInput}
            />
            <button onClick={this.addContact}>ADD</button>
          </section>
        </section>
        <hr />
        <TodoList />
      </>
    );
}
js

One input control is used to add the contact name. Once the user submits the contact, the action method should look like this.

1
2
3
4
addContact = () => {
    // Dispatching the action
    this.props.addContact(this.state.inputs.message);
};
js

There is an action called addContact() that takes the contact name as a value and will pass it to the action invocation function, but mapDispatchToProps will be used in this example.

1
2
3
4
5
const mapDispatchToProps = dispatch => {
  return {
    addContact: contact => dispatch(addContact(contact))
  };
};
js

So far, you have created a straightforward form and invoked the Redux action, but you don’t have any component to show the added list of contacts.

For that, create one additional component, as demonstrated below.

ContactList.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React, { Component } from "react";
import { connect } from "react-redux";

class ContactList extends Component {

  renderContacts = () => {
    return this.props.contacts.contacts.map((contact, i) => (
      <section key={i}>
        <div>
          <p className="flex">{contact}</p>
        </div>
      </section>
    ));
  };

  render() {
    return (
      <>
        <section>
          <section>
            <h2>CONTACTS</h2>
            <hr />
            {this.props.contacts.contacts &&
            this.props.contacts.contacts.length > 0 ? (
              this.renderContacts()
            ) : (
              <span>Contacts not found</span>
            )}
          </section>
        </section>
      </>
    );
  }
}

const mapStateToProps = state => ({ contacts: state.contacts })

export default connect(mapStateToProps)(ContactList);
jsx

In the above component, there is a function created called renderContacts() that is using this.props.contact. This means the data that is coming from the global state object is consumed in the child component.

The below statement is crucial, and extracts the required state from the store.

1
const mapStateToProps = state => ({ contacts: state.contacts })
jsx

In the above statement, state.contacts contains a piece of the global state object and is assigned to the local props called contacts, so when you want to access the contacts from the global state, you can use this.props.contacts from the existing component.

The last step is to assign mapStateToProps to the connect() function so that the props will find the suitable state object from the state.

1
export default connect(mapStateToProps)(TodoList);
jsx

Conclusion

The Redux library allows us to implement global state objects accessible from any component across the app; thus, the connect() function enables any sub-routes to in your app to extract the required state object from the store.

0