The React + Redux Container Pattern
Tags: react, redux, containercomponent, containerpattern
Published: 2017-11-12 18:45:42

---
title: The React + Redux Container Pattern
published: true
description: A deep dive into the React/Redux container pattern
tags: React, Redux, Container component, Container pattern
---
*Note: This post was first published in my blog, [The Great Code Adventure](http://www.thegreatcodeadventure.com/)*
### Building Responsive Applications, Cleanly, is Hard

The first large (okay, more like medium) scale application I built in React was pretty straightforward. It was a simple CRUD application for managing your very own list of cats and their associated hobbies (so fun). Being so straightforward, it wasn't too difficult to keep my code clean and well organized. There weren't too many fancy features, so my system of container components that fetched data and fed it to presentational components just felt kind of natural. 

My understanding of this pattern was kind of blown apart about a year ago when, as a teacher at the Flatiron School, we shepherded 26 students through a React project sprint in which they broke out into small groups to develop their own varied and complex React + Redux applications. That was where things got messy. Managing such a diverse group of projects was a great way to encounter *all* the bugs and *all* the tough design decisions, *all* at once. 

As hectic as that could be, it really drove home the utility and elegance of the container pattern in React. Instead of allowing any and all components to fetch and manipulate data, which can make debugging pretty much suck, we want to implement a pattern that's in line with the Single Responsibility Principle, and that keeps our code DRY. 

So, I thought I'd offer a deeper dive into the container pattern, and one example implementation. But before we jump into the code, let's talk about container and presentational components.

#### What's a Container Component?

![](http://www.thegreatcodeadventure.com/content/images/2016/11/6234816796_6401dd69b0_b.jpg)

When reading up on container components, I came across this phrase a lot:

> "Container components are components that are aware of Redux"
> –– *the internet*

So, what does that mean?

Well, a container component is a component that is responsible for retrieving data, and in order to get that data, the component needs to use Redux's `connect` and `mapStateToProps` functions. 

A container component will grab data from state via `mapStateToProps`. The component will then pass necessary portions of that data down to its children as `props`. 

A container component is also responsible for dispatching actions that make changes to application state.

Another phrase that I came across a lot was the distinction between "controller views" and "views". This analogy really made sense to me, coming from Rails. If React is a view-layer technology, some views nonetheless are responsible for retrieving data (*controller views*) and passing that data to other views in order to be displayed (*presentational views*). 

#### What's a Presentational Component?

If a container component is a component that actually leverages Redux to get data, a presentational component simply receives that data from its parent container and displays it. 

So, you might be wondering, if a presentational component just displays data, and the container component is the one that contains any action-firing functions, how can a user's interaction with a presentation component ultimately trigger an action? 

This is where callback props come in. 

#### Callback Functions as Props

In our upcoming example, we'll see how to define a function in a container component that dispatches an action. Such a function will be passed as prop to a child, presentational, component, and triggered via a callback, in response to a users' interaction. 

Okay, now we're *almost* ready to dive in to the code.

### Application Background

The code we'll be looking at is from an student attendance tracking application that allows students to log in and indicate that they have arrived that day. Instructors can log in and view the attendance records for their class via a color-coded calendar, clicking on a calendar day and a student name from a list of students to view the details of a student's attendance record. 

We'll be taking a closer look at the instructor side of things, implementing the container pattern to build of the ability for an instructor to select a calendar day and a student to view that student's attendance record details for that day. 

Something like this:

![](http://www.thegreatcodeadventure.com/content/images/2016/11/calendar-demo.gif)

Let's get started!

#### Component Design

When building in React, I've found it really helpful to do lots and lots of wire framing. So, before we dive in to the code, let's talk about the overall structure of our components. 

As we can see from the image above, we have a couple of distinct areas that will respond really well to componentization. The image can be broken down into three distinct parts.  

* calendar
* student list
* attendance record show

So, we'll build a container components, `ScheduleContainer`, that contains the child presentational components of calendar and attendance record show. We'll make a `StudentsContainer` component that is rendered by `ScheduleContainer` but that in turn renders a presentational component, `StudentList`. 

Something like this:

![](http://www.thegreatcodeadventure.com/content/images/2016/11/calendar-redux.png)

In order to display an attendance record detail, we need to know who the selected student is and what the selected day is. With this information, we can dip into the attendance records we have in the application's state, identify the correct attendance record, and pass it to the attendance record show component to be displayed. 

Before we worry about selecting students and dynamically rendering the correct attendance record, we'll get all of our data displaying nicely. Then, we'll move on to using callback functions to select students from `studentList` component to change the attendance record that `ScheduleContainer` passes down to `attendanceRecordShow` to display. 

#### Step 1: `connect`-ing our Container Components and Getting Data

First things first, we'll set up our top-most level container component, `ScheduleContainer`, and give it access to the data it needs from state. 

This post isn't concerned with the "back-end" of things, so we won't really be diving in to action creator functions or reducers. We'll assume that the data in state looks like this:

```javascript
{
  attendanceRecords: [
    {id: 1, date: '10-7-2017', records: [
      {id: 1, student_id: 7, arrived: true, arrivedAt:   
       '10am'}, 
      {id: 2, student_id: 8, arrived: false, arrivedAt:   
       null}]},
    {id: 2, date: '10-8-2017', records: [
      {id: 3, student_id: 7, arrived: true, arrivedAt:   
       '10:20am'}, 
      {id: 2, student_id: 8, arrived: true, arrivedAt:   
       '9:00am'},]},
  ],
  students: [
    {id: 7, firstName: "Sophie", lastName: "DeBenedetto"},   
    {id: 8, firstName: "Doctor", lastName: "Who"}, 
    {id: 9, firstName: "Amy", lastName: "Pond"}
  ]
}
```

We can see that `state` contains `attendanceRecords` and `students` and that attendance records are organized by date, with each attendance record object containing a property, `records`, which lists the records for each student for that date. 

Our `ScheduleContainer` component is mainly concerned with getting the attendance records from state, and passing them to the calendar presentational component. For my calendar, I used the React DayPicker library. 

```javascript
import React from 'react';
import DayPicker, { DateUtils } from 'react-day-picker'
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as attendanceRecordActions from '../../actions/attendanceRecordActions';

class ScheduleContainer extends React.Component {
  componentDidMount() {
    if (this.props.attendanceRecords.length = = 0) {
      this.props.actions.fetchAttendanceRecords();
    }
  }

  render() {
    return (
      < DayPicker
        locale='us'
        selectedDays={day => {
         DateUtils.isSameDay(new Date())
        }} /> 
    )
  }
}

function mapStateToProps(state, ownProps) {   
  return {attendanceRecords: state.attendanceRecords}
}

function mapDispatchToProps(dispatch) {
  return {actions: bindActionCreators(attendanceRecordActions, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(ScheduleContainer);
```

So far our component is pretty simple. It manages the following:

* Use `mapStateToProps` to get the attendance records from state and make them available to our component as props. (The default value for this key of `state` is an empty array, and it is set in the initial state of our application, not shown here.)
* Use `mapDispatchToProps` to get the `attendanceRecordActions` functions and make them available to our component under `this.props.actions`.
* Use the lifecycle method, `componentDidMount` to check if there are in fact attendance records. If not, dispatch the `fetchAttendanceRecords` action, which will make an API call, get the attendance records, populate them into application state and cause a re-render. 
* Then, render the `DayPicker` calendar component, highlighting the selected day via the `selectedDays` prop.

Currently, we're not doing anything with the attendance records we grabbed from state. So, what do we need to do with them?

We need to:

* Identify the selected day and student and render that student's record for that day.
* Allow a user to click on a calendar day and change the selected day and attendance record to view. 


#### Step 2: Passing Data Down to Presentational Components to Display

Our aim is to display the attendance record for a selected student and a selected day. Before we worry about how we will get that information, let's take build out a simple functional component to display it. 

We'll build a component, `AttendanceRecordShow`, that will be rendered by `ScheduleContainer`. Eventually, `ScheduleContainer` will pass the correct attendance record (based on selected student and day) down into this component. 

```javascript
// src/components/AttendanceRecordShow.js

import React from 'react'
import Moment from 'react-moment';

const AttendanceRecordShow = (props) => {
  function studentInfo() {
    if (props.student) {
      return (
        < p >
          record for: {props.student.first_name}{props.student.last_name}
        < /p>
    }
  }

  function recordInfo() {
    if (props.record) {
      if (props.record.arrived) {   
        const date = new Date(props.record.arrived_at)   
        return < p>arrived at: {date.toDateString()}< /p>
      } else {
        return < p>absent or late</ p>
      }
    }
  }
  return (
    < div className="col-sm-12 text-center">
      {studentInfo()}
      {recordInfo()}
      < p>{props.day.toDateString()}< /p>
    < /div>
  )
}

export default AttendanceRecordShow
```

`ScheduleContainer` will render the component like this:

```javascript
// src/components/containers/ScheduleContainer.js

class ScheduleContainer extends React.Component {
  ...
  render() {
    return (
      < DayPicker
        locale='us'
        selectedDays={day => {
         DateUtils.isSameDay(new Date())
        }} />
      < AttendanceRecordShow 
        day={we need to give it a day!} 
        student={we need to give it a student!} 
        record={we need to give it a record!}/> 

    )
}   
```

Our `ScheduleContainer` container is in charge of fetching and manipulating data, and passing it down to child functional, or presentational, components to be displayed. 

So, let's teach `ScheduleContainer` how to identify and grab the attendance record for the selected student and day, and pass that down to the appropriate presentational components. 

`ScheduleContainer` will need to keep track of the selected student, day and attendance record, and the selected student and day will change based on the user's click of a certain calendar day or student from our student list. This will in turn change the attendance record that we want to display. So, `ScheduleContainer` should keep track of this information as part of its own internal state. 

We'll start by giving `ScheduleContainer` a constructor function that sets some default values. We'll give the `selectedDay` property a default value of today's date, the `selectedStudent` property a default value of `null` and the `selectedRecord` a default value of `null`.

```javascript
// src/components/containers/ScheduleContainer.js

class ScheduleContainer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {selectedStudent: null, selectedRecord: null, selectedDay: new Date()}
  }
  ...

  render() {
    return (
      < DayPicker
        locale='us'
        selectedDays={day => {
         DateUtils.isSameDay(new Date())
        }} /> 
      < AttendanceRecordShow 
        day={this.selectedDay} 
        student={this.selectedStudent} 
        record={this.selectedRecord}/> 

    )
}   
```

We need to give the user the ability to change the selected day, i.e. to select a day. The `DayPicker` component responds to a callback function, `onClick`, that we can set to a custom function to set our selected day. This way, when a user clicks on a calendar day, we can dynamically update the `ScheduleContainer` component's state's `selectedDay` property, changing the value that we pass down into `AttendanceRecordShow`.

Let's define a function, `selectDay`, and tell it to fire as the `onClick` function for the `DayPicker` component. Our `selectDay` function has two jobs:

* Set the `ScheduleContainer` component's state's `selectedDay` property to the day that the user clicks on via the calendar. 
* If there is already a student selected, selecting a day *should change the state's `selectedRecord` property to the record of the selected student for that day*. 

```javascript
selectDay(e, day) {
    e.preventDefault();
    if (this.state.selectedStudent) {
      const recordsBySelectedDate = this.props.attendanceRecords.find(recordsByDate => {
        const date = new Date(recordsByDate.date)
        return date.toDateString() = = day.toDateString()
      })
      const record = recordsBySelectedDate.records.find(record => record.student_id = = this.state.selectedStudent.id)
      this.setState({selectedRecord: record, selectedDay: day}) 
    } else {
      this.setState({selectedDay: day})
    }
  }
```

In the function above, we first check to see if there is a `selectedStudent`, if so, we then grab the attendance records with the newly selected date, and then from that set of records, grab the record with the `student_id` of the selected student's ID. 

Next up, let's give our user the ability to select a student from our list of students. 

#### Step 3: Props as Callback Functions: Sending Actions Up from Presentational to Container Components

We'll build a presentational component, `StudentList`, that will render a list of students. A user should be able to click on any student in the list and view that student's attendance record for the selected day. 

But, our `StudentList` will need access to all of the students in order to display them. `StudentList` shouldn't fetch any data itself, or be connected to the store in any way––remember, it's just a dumb presentational component. We do have one container component `ScheduleContainer`, that is responsible for fetching data. But this container component is already fetching attendance record data. We don't want to crowd this one container component with lots and lots of data fetching responsibilities. 

So, we'll build *another container component* and have `ScheduleContainer` contain it. This illustrates an important aspect of our container pattern:

**Containers can contain other containers!**

So, we'll build another container component, `StudentsContainer`, that will fetch the student data and pass it down to a presentational component, `StudentList` as part of `props`

#### The `StudentsContainer` Component

`StudentsContainer` should follow a similar pattern to `ScheduleContainer`––use `mapStateToProps` to grab the students and use the `componentDidMount` lifecycle method to fetch students from the API if none are populated into state. 

Let's do it!

```javascript
import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as instructorActions from '../../actions/instructorActions';
import StudentList from '../studentList';

class StudentsContainer extends React.Component {
  componentDidMount() {
    if (this.props.students.length = = 0) {
      this.props.actions.fetchStudents();
    }

  }

  render() {
    return ( 
      < div className="col-lg-4">
        < h2>Students< /h2>
        < StudentList 
          students={this.props.students}/>
      < /div>

    )
  }
}

function mapStateToProps(state) {
  return {students: state.students}
}

function mapDispatchToProps(dispatch) {
  return {actions: bindActionCreators(instructorActions, dispatch)}
}

export default connect(mapStateToProps, mapDispatchToProps)(StudentsContainer);
```

This component plucks the students from state and passes them to the presentational component, `StudentList`. 

Our `StudentList` component looks something like this:

```javascript
import React from 'react'
import {ListGroup, ListGroupItem} from 'react-bootstrap'

const StudentList = (props) => {
  function studentListItems() {
    return props.students.map((student, i) => {
      return (
        < ListGroupItem>
         {student.first_name} {student.last_name}
        < /ListGroupItem>
    })
  }

  function studentListGroup() {
    return (
      < ListGroup>
        {studentListItems()}
      < /ListGroup>
    )
  }
  return (
    {studentListGroup()}
  )
}

export default StudentList;
```

`StudentList` iterates over the students stored in the `students` prop passed down from `StudentsContainer`, to collect and render a list group of student names.

The top-level container component, `ScheduleContainer` will render `StudentsContainer` like this:

```javascript
// src/components/containers/ScheduleContainer.js

class ScheduleContainer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {selectedStudent: null, selectedRecord: null, selectedDay: new Date()}
  }
  ...
  render() {
    return (
      <StudentsContainer />
      < DayPicker
        locale='us'
        selectedDays={day => {
         DateUtils.isSameDay(new Date())
        }} /> 
      < AttendanceRecordShow 
        day={this.selectedDay} 
        student={this.selectedStudent} 
        record={this.selectedRecord}/> 

    )
}
```

Now that we have our student list up and running and displaying a lovely list of students, we need to allow our user to click on a student from that list, make that student the "selected student", and display that student's attendance record for the selected day.

#### Props as Callback Functions + The "Data Down Actions Up" Principle

Remember who's in charge of identifying the attendance record? It will have to be something that knows about the selected day *and* the selected student *and* has access to all the attendance records...

It's `ScheduleContainer`! So, since it's `StudentList` that will be in charge of rendering our list of students, we'll have to teach `StudentList` how to send a message all the way back up to the top-level container, `ScheduleContainer`, and tell it to update its `selectedStudent` property in state whenever a user clicks on a student. 

We'll define a function, `selectStudent`, in `ScheduleContainer`. This function will accept an argument of the ID of the student being selected, and update `ScheduleContainer`'s state's `selectedStudent` accordingly. 

It has a second responsibility as well. It must update the `selectedRecord` property of the component's state in accordance with the newly selected student and current selected day.

Lastly, we'll have to pass this function down through `StudentsContainer`, to `StudentList` as a prop, and we'll need to `bind` `this` in the constructor function here in our top-level container in order for this to work.

```javascript
// src/components/containers/ScheduleContainer.js

class ScheduleContainer extends React.Component {
  constructor(props) {
    super(props)
    this.selectStudent = this.selectStudent.bind(this)
    this.state = {selectedStudent: null, selectedRecord: null, selectedDay: new Date()}
  }
  ...
  selectStudent(studentId) {
    const student = this.props.students.find(student => student.id = = studentId)
    var that = this
    const recordsBySelectedDate = this.props.attendanceRecords.find(recordsByDate => {
      const date = new Date(recordsByDate.date)
        return date.toDateString() == that.state.selectedDay.toDateString()
    })
    const record = recordsBySelectedDate.records.find(record => record.student_id studentId)
    this.setState({selectedStudent: student, selectedRecord: record})
  }
  render() {
    return (
      < StudentsContainer 
        selectStudent={this.selectStudent}/>
      < DayPicker
        locale='us'
        selectedDays={day => {
         DateUtils.isSameDay(new Date())
        }} /> 
      < AttendanceRecordShow 
        day={this.selectedDay} 
        student={this.selectedStudent} 
        record={this.selectedRecord}/> 

    )
}   
```

`StudentsContainer` will in turn pass the `selectStudent` function down to `StudentList`:

```javascript
import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as instructorActions from '../../actions/instructorActions';
import StudentList from '../studentList';

class StudentsContainer extends React.Component {
  componentDidMount() {
    if (this.props.students.length == 0) {
      this.props.actions.fetchStudents();
    }

  }

  render() {
    return ( 
      <div className="col-lg-4">
        <h2>Students</h2>
        <StudentList 
          students={this.props.students}
          selectStudent={this.props.selectStudent}/>
      </div>

    )
  }
}

function mapStateToProps(state) {
  return {students: state.students}
}

function mapDispatchToProps(dispatch) {
  return {actions: bindActionCreators(instructorActions, dispatch)}
}


export default connect(mapStateToProps, mapDispatchToProps)(StudentsContainer);
```

And `StudentList` will fire `selectStudent` as on `onClick` function for each student list item:

```javascript
import React from 'react'
import {ListGroup, ListGroupItem} from 'react-bootstrap'

const StudentList = (props) => {
  function triggerSelectStudent(e) {
    e.preventDefault();
    props.selectStudent(e.target.id)
  }

  function studentListItems() {
    return props.students.map((student, i) => {
      return (
        < ListGroupItem onClick={triggerSelectStudent} id={student.id}>
          {student.first_name} {student.last_name} 
        < /ListGroupItem>
      )
    })
  }

  function studentListGroup() {
    return (
      < ListGroup>
        {studentListItems()}
      < /ListGroup>
    )
  }
  return (
    {studentListGroup()}
  )
}

export default StudentList;
```

Here, we define a function `triggerSelectStudent`, that fires on the click of a student list item. The function grabs the ID of the student that was clicked on, and passes it to the invocation of the `selectStudent` function, passed down to this component as a prop. This will travel all the way back up the component tree to `ScheduleContainer`, invoking the `selectStudent` function defined there. This, by the way, is a great example of the **Data Down Actions Up** flow that React is so good at.

That function will run, changing `ScheduleContainer`'s state to have a new `selectedStudent` *and* a new `selectedRecord`, which will trigger the component to re-render. 

This will re-render the `AttendanceRecordShow` component that `ScheduleContainer` contains, rendering the newly selected attendance record for the user.

### Conclusion

Phew! We did it! Okay, that was a lot. The code offered here is a very specific approach to building out a feature for this app, but it illustrates the larger container pattern in which:

* A top-level container renders the rest of the component tree
* That container holds child presentational components, as well as other containers which in turn hold presentational components
* Containers are responsible for getting data from state and updating internal state in response to user interaction
* Presentational components are responsible for receiving data from their parents to display and alerting their parents when a user-triggered change needs to be made via the DDAU pattern

As always, there is more than one way to approach a given feature, but the implementation shown here *is* in-line with the above principles. To check our the full code for this project, you can view [this repo](https://github.com/antoinfive/flatiron-attendance-trackr-frontend). 

Happy coding!