ReactでTodoアプリの作成

ブログメインビジュアル

今回は学習中のReactでTodoアプリケーションの作成をしていきたいと思います。

余談ですが、Reactのロゴってカッコいいですよね。僕は好きです。

目次

実装機能

・ タスクの登録
・ タスクの削除

Reactアプリケーションの作成

※Nodeのインストール方法については今回は記載いたしません。

$ npx create-react-app todo-app
$ cd todo-app
$ npm start


Reactアプリのインストール初期画面

http://localhost:3000にアクセスし、こちらの画面がブラウザ上で表示されていれば、成功です。

Reactコンポーネント

Reactでは細かなUIをコンポーネント単位で管理することができ、それらを組み合わせ開発を行うことで、保守性の高いアプリケーションを実現することができます。

先ほど、作成したアプリケーションのsrcディレクトリ配下のApp.jsファイルをみていきます。

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

こちらのファイルではAppというコンポーネントを関数にて定義しています。
コンポーネントの定義には、クラスコンポーネント関数コンポーネントの2つの方法で定義することができます。

クラスコンポーネントでは、内部に状態(state)を持つことができたり、ライフサイクルメソッドの使用ができたりします。

関数コンポーネントでは、stateライフサイクルメソッドの使用はできず、ざっくりいうとクラスコンポーネントのrender部分のみ書いてるようなイメージになります。その分、簡潔にコンポーネントの定義を行うことができます。
両者とも、コンポーネント間での情報を受け渡すことができるpropsを扱うことができるので状況に応じて使い分けていきましょう。

コンポネーネント・ライフサイクルメソッドについての詳細を知りたい方は、下記をご覧ください。
コンポーネントと props
state とライフサイクル

ファイルの構成

今回は、以下のファイル構成で作成していきます。

src/
  |-- App.js
  |-- index.js
  |-- components/
    |-- List.js
    |-- Form.js

タスクの登録

まず、App.jsにてAppコンポーネントの中身を変更していきます。今回はタスクの登録するための、statevaluetodosAppコンポーネント内で管理していきたいので、クラスコンポーネントで定義します。

App.js

import React from 'react';
import Form from './components/Form.js'   //Formコンポーネントの呼び出し

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      value: '',
      todos: [],
    }
  }

  handleChange = (e) => {
    this.setState ({ value : e.target.value })  //入力された文字
  }

  handleSubmit = (e) => {
    e.preventDefault();
    if(this.state.value === '') return  //空文字の登録を不可にする
    this.state.todos.push(this.state.value)  //todosにvalueを追加
    this.setState({  //setState()内でstateの値を変更
      todos: this.state.todos,
      value: '',  //フォームに入力されている文字を空にする
    })
  }

  render(){
    return(
      <React.Fragment>
        <Form   //Formコンポーネントに関数とstateを渡す
          handleChange={this.handleChange}
          handleSubmit={this.handleSubmit}
          value={this.state.value}
        />
      </React.Fragment>
    )
  }
}

export default App;

Form.js

import React from 'react';

const Form = props => {   //引数でAppコンポーネントからpropsを受け取る。
  return (
    <form onSubmit={props.handleSubmit}>
      <input
        type="text"
        onChange={props.handleChange}
        value={props.value}
      />
      <button type="submit">Add</button>
    </form>
  )
}

export default Form;

今回は、AppコンポーネントからFormコンポーネントに下記の3つを渡しています。

 <Form
    handleChange={this.handleChange}
    handleSubmit={this.handleSubmit}
    value={this.state.value}
  />

propsの確認はchormeの拡張機能のReact Developer Tools をインストールすると手軽に確認することができます。

FormコンポーネントhandleChangehandleSubmitvalueが渡されていることが確認できます。

React Developer Tools画面

登録したタスクの表示と削除

Appコンポーネント内で削除機能のhandleRemoveを作成し、todosと一緒にListコンポーネントに渡してあげます。

App.js

import React from 'react';
import Form from './components/Form.js'
import List from './components/List.js'   //Listコンポーネントの呼び出し

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      value: '',
      todos: [],
    }
  }

  handleChange = (e) => {
    this.setState ({ value : e.target.value })
  }

  handleSubmit = (e) => {
    e.preventDefault();
    if(this.state.value === '') return
    this.state.todos.push(this.state.value)
    this.setState({
      todos: this.state.todos,
      value: '',
    })
  }

  handleRemove = (i) => {   //引数でiを受け取る
    this.state.todos.splice(i,1)  //i番目の要素を削除する
    this.setState({
      todos: this.state.todos
    })
  }

  render(){
    return(
      <React.Fragment>
        <Form
          handleChange={this.handleChange}
          handleSubmit={this.handleSubmit}
          value={this.state.value}
        />
        <List   //ListコンポーネントにtodosとhandleRemoveを渡す。
          todos={this.state.todos}
          handleRemove={this.handleRemove}
        />
      </React.Fragment>
    )
  }
}

export default App;

List.js

Listコンポーネント内で受け取ったtodosを、mapメソッドにて展開します。その際に必ずkeyを持たせてあげることに注意してください。

import React from 'react';

const List = props => {
  return (
    <ul>
      {props.todos.map((todo,i) => ( //受け取ったtodosをmapメソッドにて展開
        <li key={i}>
          {todo}
          <button onClick={() => props.handleRemove(i)}>Delete</button> //引数で削除したいタスクの番号(i)を渡す
        </li>
      ))}
    </ul>
  )
}

export default List;



こちらが完成イメージになります。 完成イメージ

まとめ

今回は、Reactの基本であるコンポーネント、state、propsを用いてTodoアプリケーションの作成しました。
少しでも参考にしていただければ、幸いです。

この記事を書いた人 kito エンジニアになるために愛知から上京しました。
TOP