Building a Simple React App - Part 2
Tags: app, react
Published: 2020-03-04 08:52:09

---
title: Building a Simple React App - Part 2
published: true
description: This is the second part of the series of articles about how to build a simple app in React.
tags: app, react
---

In the [previous part](https://kolosek.com/building-simple-react-app-part-1/) of *How to build simple React app*, we had set up basic boiler-plate for our ToDo application. In this part we will:
- start building our application logic,
- introduce actions and reducers,
- finish our todo page

Let's start coding!

## Writing new components for handling todos

On start we will focus only on functionality, a style will be added later. So for our todos, we will create a `TodoList` component, which will render `Todo` components for each todo it gets. So let's look at `TodoList` component.

```javascript
// src/components/Home/TodoList/TodoList.jsx

import React from 'react';
import PropTypes from 'prop-types';

import Todo from './Todo/Todo';
import AddTodo from './AddTodo/AddTodo';


const TodoList = ({ todos, setTodoDone, deleteTodo, addTodo }) => (
  <div className="todos-holder">
    <h1>Todos go here!</h1>
    <AddTodo addTodo={addTodo} />
    <ul className="todo-list">
      {todos.map((todo) => <Todo key={`TODO#ID_${todo.id}`} todo={todo} setDone={setTodoDone} deleteTodo={deleteTodo} />)}
    </ul>
  </div>
);

TodoList.propTypes = {
  todos: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    task: PropTypes.string.isRequired,
    done: PropTypes.bool.isRequired
  })).isRequired,
  setTodoDone: PropTypes.func.isRequired,
  deleteTodo: PropTypes.func.isRequired,
  addTodo: PropTypes.func.isRequired
};

export default TodoList;    
```

Pretty straightforward component, written as **dumb** component (if you recall, in previous part I recommended writing all components as dumb on the beginning). It has a heading, `AddTodo` component, which we will take a look into in a moment, and one unordered list in which all todos are rendered, in form of `Todo` component.

New part here is the usage of **prop-types**. *Prop-types* gives us a possibility of *type checking*. Its main idea is to define types of *props* component will receive, which gives you more clarity when writing component, and more verbosity when debugging (for example if something marked as required is not set, you will see console error for that, or if something is sent, but type doesn't match, you will also see console error). More about *prop-types* and rules for writing them you can find [here](https://facebook.github.io/react/docs/typechecking-with-proptypes.html). We defined *"todos"* as array of objects having a **shape** as described, and marked that array as **required**. Shape of each todo is described by **id** number required the value, the **task** as a required string, and **done** required boolean flag. **addTodo**, **setTodoDone**, and **deleteTodo** are *props* defined as functions and all required.

Don't worry for now from where `TodoList` will get its props, we will get to that later, for now just note that we are assuming that those props are passed to the component from somewhere.

Next component we obviously need is `AddTodo` component. Let's take a look at `AddTodo` implementation.

```javascript
// src/components/Home/TodoList/AddTodo/AddTodo.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';


class AddTodo extends Component {

  static propTypes = {
    addTodo: PropTypes.func.isRequired
  }

  constructor(props) {
    super(props);

    this.state = {
      task: ''
    };

    this.changeTaskText = this.changeTaskText.bind(this);
    this.submitTask = this.submitTask.bind(this);
  }

  changeTaskText(e: Event) {
    e.preventDefault();  // optional, not necessary in this case, but for consistency

    this.setState({ task: e.target.value });
  }

  submitTask(e: Event) {
    e.preventDefault();  // optional, not necessary in this case, but for consistency

    this.setState({ task: '' });
    this.props.addTodo(this.state.task);
  }

  render() {
    return (
    <div>
      <input type="text" onChange={this.changeTaskText} value={this.state.task} placeholder="Task text" />
      <button onClick={this.submitTask}>Add Todo</button>
    </div>
    );
  }
}

export default AddTodo;
```

This component is written in `class` form because it uses internal state. Generally, component internal state **should be avoided** because it makes testing harder, separates a component from global application state (which is the main idea behind redux/flux), but here it is implemented this way, mainly to show one component written through `class`.

`AddTodo` component, as we already said, have its internal state storing task text (which is read from input field), and two custom methods (functions) `changeText` and `submitTask`. The `changeText` method is triggered by any change event inside input field, while `submitTask` is triggered only by *Add Todo* button click. Both methods are simple ones, `changeText` just sets an internal state *task* to received text, and `submitTask` restarts text inside internal state, and submits current text (from the internal state) through only *prop* component received, `addTodo`. The interesting thing here is the order of actions, it first restarts text, and then submits text which is inside the state, but it still works as it is supposed to. How? Component's `setState` method is an async method, which means that it won't change state immediately, but in next process tick, so we can do something like that. You should probably reverse order of this two lines, just for clarity, I just wanted to share that *fun fact* with you.

Prop types in this component (and in all `class` defined components) are defined as a **static** attribute of the class. `AddTodo` only has one prop (and it is required), `addTodo` function. In this case, it gets that prop from `TodoList` component, but it may be extracted from somewhere else, doesn't matter, the only thing that matters inside `AddTodo` is that `addTodo` is function and passed through props.

Next thing we want to take a look is `Todo` component.

```javascript
// src/components/Home/TodoList/Todo/Todo.jsx

import React from 'react';
import PropTypes from 'prop-types';


const Todo = ({ todo, setDone, deleteTodo }) => (
  <li style={{ textDecoration: (todo.done ? "line-through" : "") }}>
    {todo.task}&nbsp;
    <button className="done-button" onClick={() => setDone(todo.id, !todo.done)}>{todo.done ? "Activate" : "Set Done"}</button>&nbsp;
    <button className="delete-button" onClick={() => deleteTodo(todo.id)}>Delete</button>
  </li>
);

Todo.propTypes = {
  todo: PropTypes.shape({
    id: PropTypes.number.isRequired,
    task: PropTypes.string.isRequired,
    done: PropTypes.bool.isRequired
  }).isRequired,
  setDone: PropTypes.func.isRequired,
  deleteTodo: PropTypes.func.isRequired
};

export default Todo;
```

This component is the presentation of one Todo item. It is wrapped inside `<li>` tag, has todo's task text and two buttons, one for marking todo as done or undone (same button, same action, different parameter), and one for deleting todo. Both buttons trigger functions which are just delegating the job to function given through *props*, with appropriate attributes (values). As far as prop-types are concerned, it has `todo` key (defined same as the todo in `TodoList` component), `setDone` required function and `deleteTodo` required function.

Before we carry on with components, let's talk a little bit about presentational and container components. There is this *pattern* which states that all react components are divided into two groups, **presentational** and **container** components. **Presentational** components are responsible for rendering content, how things will look like on screen. They are not responsible for fetching or mutating data, they just receive data through props, and create an appropriate layout for that data. Usually, they are written as **dumb** components, and they can hold other presentational or container components, doesn't  matter. Unlike them, **container** components, are responsible for data fetching and mutating. Their job is to provide data to presentational components, and to provide callbacks (hooks) for mutating data, most often the same to presentational components. There is one nice article describing this *pattern* here is the [link](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0), just note that in that article **dumb** component is practically the synonym for the **presentational** component, while in this article **dumb** component has other meaning.

Having in mind what I just described about presentational and container components, you can see that all our components are presentational. Neither one of them is concerned about data fetching or mutating, they all just display data, and link callbacks (hooks) for mutation to user controls (buttons). There is no real source of data or mutation callbacks, it all comes from `TodoList` which gets it from props, but where does `TodoList` get them from?

## `TodoListContainer` component, actions, and reducers

Now we will create our first **container** component, which will handle fetching data (for now just from reducer - application state), and provide callbacks for the mutation (modification).

```javascript
// src/components/Home/TodoList/TodoListContainer.js

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import { setTodoDone, deleteTodo, addTodo } from './actions/todoActions';
import TodoList from './TodoList';


const mapStateToProps = state => ({
  todos: state.todoReducer.todos
});

const mapDispatchToProps = dispatch => bindActionCreators({
  setTodoDone,
  deleteTodo,
  addTodo
}, dispatch)


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

Here we have few new concepts. First of all, as you may have noticed, the real definition of the component doesn't even exist here. In `export default` part we just wrapped our `TodoList` component in some function and returned that. What is this actually? It's just a wrapper which subscribes component to global application state (reducer) and provides data (and functions) as props to the wrapped component. So this is the part where real data is *"injected"* into our components.

`connect` function accepts two functions as parameters and creates a wrapper which then accepts component to wrap. First function passed to connect is `mapStateToProps`, function which gets `state` (global state, which is created by `combineReducers` in our `src/reducers.js` added to a `store` object in our `src/index.js` and injected in global wrapper `<Provider>` also in `src/index.js`) and returns object with keys (extracted from state) which will be passed as props to wrapped component. Second function passed to connect is `mapDispatchToProps`, function which gets `dispatch` (callback we will get back to this in [Part 3](https://kolosek.com/building-simple-react-app-part-3/) where we will take a look into creating async actions), and returns object containing "function name - function" pairs (that functions are actually **actions**) which will also be passed as props to wrapped component.

This is a pretty important part, it is the link between simple components, and application state, a part that actually connects all parts of redux as a functional whole. One more handy thing `connect` do for us, is *"subscribing"* to a part of the state we are passing to the wrapped component, so any time that part of the state is changed (**only through reducers!**), our wrapped component will receive new (changed) props. It is like we have some event listener, which listens for change events only for those parts of the global state we *"subscribed"* on.

In our `mapStateToProps` we connected `state.todoReducer.todos` to a `todos` key. That is nice, but we need `todoReducer`, if you take a look in `src/reducers.js` it is just an empty object, we need to create `todoReducer`, with `todos` key. Also in `mapDispatchToProps` we are using `bindActionCreators` function (this will also be explained later, for now just think of it as a helper) to wrap our object containing **actions**. But we still need those actions in code. So let's start with our actions, and then take a look at our `todoReducer`.

```javascript
// src/components/Home/TodoList/actions/todoActions.js

import * as types from '../constants';


export const setTodoDone = (id: Number, done: Boolean) => ({
  type: types.SET_TODO_DONE,
  payload: {
    id,
    done
  }
});

export const deleteTodo = (id: Number) => ({
  type: types.DELETE_TODO,
  payload: {
    id
  }
});

export const addTodo = (task: String) => ({
  type: types.ADD_TODO,
  payload: {
    task
  }
});
```

It is just a JavaScript file containing a bunch of functions. Every function is returning some kind of object. That object is actually an **action**, and these functions are **action creators**. In this article, whenever I said actions I was referring to "action creators", and when I want to refer action I will say "action object", that is pretty common notation. Each action object has to have **type** key, representing identification by which it will be recognized in reducers, other keys are optional. For consistency, I like to all other data put inside **payload** key so that each action object has the same structure. Actions (action creators) can accept parameters however you want because, in the end, they are just a simple plain functions which will be called from somewhere in your code (components). These returned objects (action objects) are automatically dispatched in the system (automatically thanks to the `bindActionCreators` method, but more on that later), and main reducer (optionally combined from other reducers - in our case in `src/reducers.js` with function `combineReducers`) will get called with that action object as a second parameter. Let's now take a look into our `todoReducer.js`

```javascript
// src/components/Home/TodoList/reducers/todoReducer.js

import { Record } from 'immutable';
import * as types from '../constants';

import { getLastId } from '../../../../utils/todoUtils';


const TodoState = new Record({
  todos: [
    { id: 1, task: "This is todo 1", done: false },
    { id: 2, task: "This is todo 2", done: false },
    { id: 3, task: "This is todo 3", done: true }
  ]
});

const initialState = new TodoState();

const todoReducer = (state = initialState, action) => {
  switch(action.type) {
    case types.SET_TODO_DONE:
      return state.set('todos', state.todos.map((todo) => todo.id === action.payload.id ? { ...todo, done: action.payload.done } : todo));
    case types.DELETE_TODO:
      return state.set('todos', state.todos.filter((todo) => todo.id !== action.payload.id));
    case types.ADD_TODO:
      return state.set('todos', [ ...state.todos, { id: getLastId(state.todos) + 1, task: action.payload.task, done: false } ]);

    default:
      return state;
  }
}

export default todoReducer;
```

Let's start from thr top. First, we defined initial state using **immutable Record**. That ensures that state won't be changed manually, only through the public interface (`set` method), which is useful because any manual changes made to state won't be recognized, and *"event"* for state change won't be fired. We could do that with `Object.assign`, by making a new instance of state each time we change something, `immutable` provides the same result but with a bunch of optimizations.

**reducer** is actually just a function, which gets the current state as the first parameter, and action object which caused invoking function (action creator created and dispatched that action object), as a second parameter. So everything that reducer is doing is actually just mutating state depending on received action object. Before I mentioned that each action object has to have **type** key, by that key reducer recognizes which action actually invoked change, and knows how to handle that concrete action. One more time, you can't modify state object manually, it is possible to do something like
```javascript
state.todos.push({ 
  id: -1,
  task: 'Invalid modification of state',
  done: false
});
```
but don't! This type of change won't trigger *"change event"*, so all components that are subscribed won't get the signal that anything changed.

One common thing that both actions and reducer use (import) is the `constants.js` file, which we haven't show yet. It is just a simple collection of constants, for simpler connection between them (recognition of action objects inside reducer).

```javascript
// src/components/Home/TodoList/constants.js

export const SET_TODO_DONE = 'SET_TODO_DONE';
export const DELETE_TODO = 'DELETE_TODO';
export const ADD_TODO = 'ADD_TODO';
```

Let's now analyze each case in our reducer. First case is `SET_TODO_DONE`

```javascript
// action object
{
  type: types.SET_TODO_DONE,
  payload: {
    id,
    done
  }
}

// reducer handler
case types.SET_TODO_DONE:
      return state.set('todos', state.todos.map((todo) => todo.id === action.payload.id ? { ...todo, done: action.payload.done } : todo));
```

So in reducer, we go through current state todos, and checking if given todo id matches one sent through action object (in `payload.id`), when it match, we replace that todo object with new object, by copying all key-value pairs from old object (using [spread operator](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator)), and overriding done key with value passed through action object. And in the end, newly created list we set as new state `todos`.

Next case is `DELETE_TODO`

```javascript
// action object
{
  type: types.DELETE_TODO,
  payload: {
    id
  }
}

// reducer handler
case types.DELETE_TODO:
      return state.set('todos', state.todos.filter((todo) => todo.id !== action.payload.id));
```

Simple handler, just filter current state todos to extract todo with given id (`payload.id`). Filtered list is then set as `todos` key in new state.

And the last case is `ADD_TODO`

```javascript
// action object
{
  type: types.ADD_TODO,
  payload: {
    task
  }
}

// reducer handler
case types.ADD_TODO:
      return state.set('todos', [ ...state.todos, { id: getLastId(state.todos) + 1, task: action.payload.task, done: false } ]);
```

Here action object has only `task` key in `payload`, that is because `done` is by default false, and `id` is auto-generated. Here we just copy all of current state todos into new list and add new object, with auto-generated id, task from `payload.task` and default false for done. Generation of `id` is done through helper function in our `src/utils/todoUtils`.

```javascript
// src/utils/todoUtils.js

export const getLastId = (todoList: Array) => {
  let lastId = 0;
  todoList.map((todo) => lastId = (todo.id > lastId ? todo.id : lastId));

  return lastId;
}
```

For now, it just contains that one function, which is pretty basic. Goes through given list, finds biggest id, and returns that. The default value is 0 so if no todos are sent, it will return 0, and in our generator, we always add + 1 on last id, so minimal id will be 1.

## Connecting all the parts together

Ok, so, we defined our actions, our reducer, and all components that we need, now it's time to include them somewhere in our application. In our `TodoListContainer`, we referenced todos from reducer with `state.todoReducer.todos`, and in our reducer, we only have `todos` key, so that means that whole reducer will be registered under `todoReducer` inside global one. That would be simple enough.

```javascript
// src/reducers.js

...
import todoReducer from './components/Home/TodoList/reducers/todoReducer';
...

const appReducer = combineReducers({
  // here will go real reducers
  todoReducer
});
...
```

In our main reducer creator, we just imported our reducer and inserted it inside appReducer under the name (key) `todoReducer`. That will give us access to all data from new reducer inside global applications state.

And the last thing we need to do to make this work (show on our screen) is to actually render our `TodoList`. 

```javascript
// src/components/Home/Home.jsx

...
import TodoList from './TodoList/TodoListContainer';
...
```

First, we need to import our component inside `Home` because that is where we want to render our list. Note that we imported from `TodoListContainer` and not `TodoList`, why is that? Because we need a component which has data and function, we don't want to provide custom data or functions to it, here we need it independent. Next, we want to actually render component, so we insert

```javascript
<div>
  <TodoList />
</div>
```

just bellow ending `</p>` tag in default render method. And that is it. Now if you start application you shouldn't get any warnings or errors.

You can play around with options, it will all work. Each time when you restart browser tab, it will go to this initial data set (because we haven't connected our reducers to some persistent data, but only to our initial state).

## Conclusion

That is all for this part. It has much information, go through this part more times if you need to, it is important to get all the concepts described here because everything else is built on them. If you haven't read first part you can read it [here](https://kolosek.com/building-simple-react-app-part-1/). In next part, we will focus on async actions, and connecting the application with RESTful API (that is why we need async actions). See you in [part 3](https://kolosek.com/building-simple-react-app-part-3/).

*Originally published at [Kolosek blog](https://kolosek.com/building-simple-react-app-part-2/).*