React from scratch Part 2
Tags: react, javascript, beginners, tutorial
Published: 2020-08-30 07:26:06

This is the second part of the series "React from scratch". This time we will start creating a To-Do-Application with the setup we did in part 1!

## Prerequisites
Part 2 will start where we left off in part 1. If you didn't already, go ahead and finish [part 1](https://dev.to/jakobkit/react-from-scratch-part-1-3lmn) or just [clone it from my repo](https://github.com/JakobKIT/getting-started-react) and start from there.

## New depdendencies
Before we start creating the To-Do-Application, we will add bootstrap as a css library to make our life easier and our routing-tools:
```Shell
$ npm i bootstrap react-router react-router-dom
```
- ***[bootstraps](https://getbootstrap.com/):*** A css library for building responsive web apps.
- ***[react-router](https://www.npmjs.com/package/react-router):*** Core routing functionality for react.
- ***[react-router-dom](https://www.npmjs.com/package/react-router-dom):*** DOM bindings for react-router.

Next we will import bootstrap into our **index.scss** by adding the following line at the top of the file:

```SCSS
@import "~bootstrap/scss/bootstrap";
```
After that we create two new directories in our *src-folder*, one for our components and one for our containers:
```Shell
$ mkdir containers
$ mkdir components
```

## Containers & components
I like to make a clear distinction between *containers* and *components*.
- **Container** are only there for displaying our UI using the functionality we provide for them. They don't implement functions.
- **Components** contain the logic for our application and "decide" which *containers* to display at which time. They provide the functionality for the containers, by passing it to them.

Now let's start writing our first *container*:

```JSX
import React from 'react';
import Routes from '../Routes';

const Root = () => (
    <Routes />
);

export default Root;
```
This containers only job is to return our application routes. These **Routes** will keep track of all different routes-component-pairs.
Create a new file in the *src-folder* called **Routes.js** with the following content:
```JSX
import React from 'react';
import { Switch, HashRouter } from 'react-router-dom';
import { Route } from 'react-router';
import TodoPage from './components/Todo';

export function Routes() {
  return (
    <HashRouter>
      <Switch>
        <Route path='/' component={TodoPage} />
      </Switch>
    </HashRouter>
  );
}

export default Routes;
```
As you can see we used our newly added dependencies in this function. 
**Switch** contains all our routes that we will declare in this application.
Currently we only declared one route which points to this address "http://localhost:8000/".
The component **TodoPage** will be rendered at this address.

Next up we need to implement TodoPage. Therefore we will create a new file called **Todo.js** in the components folder.
The file should look like this:
```JSX
import React, { Component, Fragment } from 'react'
import TodoListContainer from '../containers/TodoList';

export class Todo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      todos: [
        {
          id: 1,
          title: 'Create Part 1',
          text: 'Starting with project setup'
        },
        {
          id: 2,
          title: 'Create Part 2',
          text: 'creating the UI with components and containers'
        },
        {
          id: 3,
          title: 'Create Part 3',
          text: 'To be decided'
        }
      ],
    };
  }

  render() {
    return (
      <Fragment>
        <div className="container-fluid">          
          <TodoListContainer 
            todos={this.state.todos}
          />
        </div>
      </Fragment>
    );
  }
}

export default Todo;
```
In this file we create some dummy-todo's.
After that we pass the todo's to our *TodoListContainer* that we write next.
For that we need to create a file in the containers-folder called **TodoList** and add the following content:
```JSX
import React, { Fragment } from 'react';

const TodoListContainer = ({todos}) => (
  <Fragment>
    {
      todos.map(({id, title, text}) => (
          <div className="mb-3 card" key={id}>
            <div className="card-header">
              <h5>{title}</h5>
            </div>
            <div className="card-body">
              <p className="card-text">{text}</p>
            </div>
            <div className="card-footer">
              <button className="btn btn-primary w-25">Edit</button>
              <button className="btn btn-success ml-2 w-25">Check</button>
            </div>
          </div>
        )
      )
    }
  </Fragment>
);

export default TodoListContainer;
```
In this container we loop over all the todo's we passed down from our Todo-component.
While looping through them we create a bootstrap card for each todo, to display the title and the text.
Next we change our background color to something more suitable than red.
For that we open our **index.scss** and change the background-color as follows:
```SCSS
@import "~bootstrap/scss/bootstrap";

body {
  background-color: #d7dfdb;
}
```
Now we clean up our **index.js** by getting rid of the App-function and implementing our *Root-container* like this:
```JSX
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';
import Root from './containers/Root';
import './index.scss';

ReactDOM.render(
  <StrictMode>
    <Root />
  </StrictMode>,
  document.querySelector('#root'),
);
```
Let's startup our project via *npm start* and look at the layout we just build. It should look like this:
![Todo-App](https://dev-to-uploads.s3.amazonaws.com/i/m4s3bzyp6q6j927ukfoa.PNG)

## More functionality
Now we will add the functionality to add a new todo to our list.
First thing we have to do is to setup our **Todo-Component** to display an add-button.
Furthermore we need to implement the functionality to add a new todo to our todos-array. 

For that we have to modify our **Todo.js** as follows:
```JSX
import React, { Component, Fragment } from 'react'
import TodoListContainer from '../containers/TodoList';
import NewTodoContainer from '../containers/NewTodo';

export class Todo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showNewTodo: false,
      title: '',
      text: '',
      todos: [
        {
          id: 1,
          title: 'Create Part 1',
          text: 'Starting with project setup'
        },
        {
          id: 2,
          title: 'Create Part 2',
          text: 'creating the UI with components and containers'
        },
        {
          id: 3,
          title: 'Create Part 3',
          text: 'To be decided'
        }
      ],
    };
  }

  toggleNewTodo() {
    this.setState({
      showNewTodo: !this.state.showNewTodo
    });
  }

  onChange(event) {
    this.setState({ [event.target.name]: event.target.value });
  }

  onSubmit(event) {
    event.preventDefault();
    const { text, title } = this.state;
    this.setState({
      todos: [{ id: this.state.todos.length + 1, title, text }, ...this.state.todos],
      showNewTodo: false,
      title: '',
      text: '',
    });
  }

  render() {
    const { showNewTodo } = this.state;
    return (
      <Fragment>
        <div className="container-fluid">
          <div className="col w-25 mt-4 mx-auto">
            { showNewTodo ? 
              (<Fragment>
                <button className="mb-2 w-100 btn btn-danger" onClick={this.toggleNewTodo.bind(this)}>Cancel</button> 
                <NewTodoContainer 
                  onChange={this.onChange.bind(this)}
                  onSubmit={this.onSubmit.bind(this)} />
              </Fragment>)
              : (<button className="mb-2 w-100 btn btn-success" onClick={this.toggleNewTodo.bind(this)}>Add Todo</button>)
              }
            <TodoListContainer 
              todos={this.state.todos}
            />
          </div>
        </div>
      </Fragment>
    );
  }
}

export default Todo;
```
First of all I added three new properties to our state.

*showNewTodo* is a boolean that helps us to toggle between the add-button and the add new todo form.

*title* and *text* will contain the title and text for the new todo.

Next up I added two new function. *onChange* writes the title and text of our new todo into the state.

*onSubmit* creates a new todo-object and adds it to the front of our todos array.

And last but not least we added the necessary HTML to show the add-button or the NewTodoContainer depending on our *showNewTodo* boolean.

Now we just need to create a new file in the *containers-folder* called **NewTodo.js** and add the following content:
```JSX
import React from 'react';

const NewTodoContainer = ({onChange, onSubmit}) => (
  <form className="mb-4">
    <fieldset>
      <legend>New Todo</legend>
    </fieldset>
    <div className="form-group">
      <label htmlFor="title">Title</label>
      <input type="text" name="title" className="form-control" id="title" placeholder="Enter title" onChange={onChange} />
    </div>
    <div className="form-group">
      <label htmlFor="text">Text</label>
      <input type="text" id="text" name="text" className="form-control" placeholder="Enter text..." onChange={onChange} />
    </div>
    <button type="submit" className="btn btn-primary" onClick={onSubmit}>Submit</button>
  </form>
);

export default NewTodoContainer;
```
This is just a simple form with two input fields, that both implement our *onChange-function* and a submit-button that implements our *onSubmit-function*.
Now that this is done, we can restart our development server by hitting *npm start*.

You should see this:

![Todo-App2](https://dev-to-uploads.s3.amazonaws.com/i/jhcn77mczd1763ewd502.PNG)

And after hitting the "Add Todo"-button it should look like this:

![Todo-App](https://dev-to-uploads.s3.amazonaws.com/i/zushx1hjjvwy9ahgch3p.PNG)

## Conclusion
That's it for part 2 of this series.
We implemented some basic routing and a component that handles everything regarding our todos.
Furthermore we implemented some UI-Elements like a add-todo-form and a list of all todos.
I hope you enjoyed it!
For the next part we will finally be tackling redux and statemanagement in react and adding some more features to our application.


All the code for this multipart series can be found in this [GitHub-Repository](https://github.com/JakobKIT/getting-started-react).