4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React入門 第二章 ~Reactを使ってみよう Todoアプリ~

Last updated at Posted at 2020-05-23

#React入門目次

  1. 第一章 ~環境構築 Hello React!!~
  2. 第二章 ~Reactを使ってみよう~
  3. 第三章 ~Reactでhooksを使おう~
  4. 第四章 ~ReactでAPI通信をしてみよう(axios使用)~
  5. 第五章 ~ReactにReduxを組み込もう(hooks仕様)~
  6. 第六章 ~React × Reduxをtypescriptで書こう(hooks仕様)~
  7. 第七章 ~React × Redux × typescriptでAPI通信(redux-saga・axios・hooks仕様)
  8. 番外編 ~atomic designとは~

##初めに
Reactを学びたい・使いたいと考えている人・SPA作りたい人向けにReactの基本からreduxやtypescript等の応用を導入するところまで説明していきます。(順次公開していきます)

##第二章 ~Reactを使ってみよう~
今回はReactを実際に使ってReactの使い方を説明していきます。

####第二章の流れ

  1. Reactとは
  2. コンポーネントを作ってみよう
  3. クラス記法とfunction記法
  4. todoアプリを作ろう
  5. 練習問題

####1. Reactとは
Reactとはユーザーインターフェイス構築の為のJavaScriptライブラリです。
主にSPA(シングルページアプリケーション)の構築に使われています。
大きな特徴としては3つあります。

  1. コンポーネント指向によりUIの高再利用性: 一度作ったUIを他の画面・アプリケーション等で使いまわせる
  2. 仮想DOMによるレンダリングコストの削減: 変更箇所の差分検知=>差分箇所の変更をする事で従来の全てを作り直すDOM処理より変更が高速になる。
  3. jsx記法: JavaScript内にHTMLを書くような書き方ができる。

####2. コンポーネントを作ってみよう
まずプロジェクトを作ります。
今回はtodoアプリを作っていくのでプロジェクト名react-todoで作ります。
下記のコマンドでプロジェクトを作ります。

create-react-app react_todo

srcの配下にcomponentsという名前でフォルダーを作ります。
componentsにTodo.jsxというファイルを作ります。

コード内容の説明
constructor内でstateを初期化しています。
returnでtodoを表示するpタグを作っています。
export default TodoでTodoコンポーネントを別ファイルでimportできるようにしています。

src/components/Todo.jsx
import React from "react";
class Todo extends React.Component{
    constructor(props){
        super();
        this.state = {
            todo: "react勉強中"
        }
    }
    render(){
        return(
            <div>
                <p>{this.state.todo}</p>
            </div>
        );
    }
}
export default Todo;

App.jsでTodo.jsxをimportし、今作ったTodoコンポーネントを反映させます。

src/App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/Todo'

function App() {
  return (
    <div className="App">
      <Todo/>
      <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;

では結果を見ます。
下記コマンドで起動してください。

npm start

結果画面

image.png

####3. クラス記法とfunction記法
Reactにはいくつか書き方があります。
classでコンポーネントを作る記法とfunctionでコンポーネントを作る記法です。

先ほど作ったコンポーネントはclass記法で書いていましたが、
function記法でも同じ結果を作ることができます。

下記のようにTodo.jsxを書き直してみてください。
function記法とhooksを使った書き方です。

src/components/Todo.jsx
import React, {useEffect, useState} from 'react';
/*
class Todo extends React.Component{
    constructor(props){
        super();
        this.state = {
            todo: "react勉強中"
        }
    }
    render(){
        return(
            <div>
                <p>{this.state.todo}</p>
            </div>
        );
    }
}
*/
const Todo = (props) =>{
    const[todo, setTodo] = useState([]);
    useEffect(() => {
        setTodo("react勉強中 function")
    },[])
    return(
        <div>
            <p>{todo}</p>
        </div>
    );
}
export default Todo;

結果
image.png

ではどちらを使った方がいいのかという疑問が湧くと思います。
個人的にはfunction記法をお勧めします。

よく知りたいという方は下記URL等でご確認ください。
https://overreacted.io/ja/how-are-function-components-different-from-classes/

最初は記法が何種類かあるんだなと思ってもらい自分と違う記法を見ても驚かないようにしておけば大丈夫だと思います。
今回はclassコンポーネントで作っていきます。

####4. todoアプリを作ろう

まずはAppjsxのファイルの一つのコンポーネントだけでTodoアプリを作ります。
App.jsxを下記のコードに書き換えます。

src/App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/Todo'

class App extends React.Component {
  constructor(props){
    super();
    this.state = {
        todoList: ["React勉強", "todoアプリ作成"]
    }
    this.handleAdd = this.handleAdd.bind(this);
  }
  handleAdd(e){
    e.preventDefault();
    this.state.todoList.push(e.target.todo.value);
    this.setState(this.state.todoList);
    e.target.todo.value = '';
  }
  render(){
    
      return(
          <div>
            <form onSubmit={this.handleAdd}>
              <input type="text" name="todo"/>
              <input type="submit" value="追加"/>
            </form>
              <ul>
              {this.state.todoList.map(
                (item, i) => {
                    return<li key={i}>{item}</li>
                }
              )}
              </ul>
          </div>
      );
  }
}

export default App;

結果
textBoxの中にtodoを入力して追加ボタンを押しtodoを追加してみてください。
image.png

これでTodoアプリ自体は完成ですが、これはReactらしい書き方では無くReactを活かせていません。
なぜなら、コンポーネント指向で作っていないからです。

ではコンポーネントを分けて作っていきます。
今回はForm部分とList部分でそれぞれコンポーネントを作りAppコンポーネントで合わせる方法でやります。

まず、componentsフォルダにForm.jsxとTodoList.jsxを作ってください。

それぞれのファイルに下記のコードを書いてください。

components/Form.jsx
import React from 'react';

class Form extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      input: ''
    };
  }
  handleChange = e => {
    this.setState({ input: e.currentTarget.value })
  };

  handleSubmit = e => {
    e.preventDefault();
    this.props.onSubmit(this.state.input);
    this.setState({ input: '' })
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" value={this.state.input} onChange={this.handleChange} />
        <button>追加</button>
      </form>
    );
  }
  
}

export default Form;
components/TodoList.jsx
import React from 'react';

class TodoList extends React.Component {
  render() {
    const {todoList} = this.props 
    return (
      <div>
            <ul>
              {todoList.map(
                (item, i) => {
                    return<li key={i}>{item}</li>
                }
              )}
            </ul>
      </div>
    )
  }
}
export default TodoList;

App.jsxを書き変えます。

App.jsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/Todo'
import Form from './components/Form';
import TodoList from './components/TodoList';

class App extends React.Component {
  constructor(props){
    super();
    this.state = {
        todoList: ["React勉強", "todoアプリ作成"]
    }
    this.handleAdd = this.handleAdd.bind(this);
  }
  handleAdd(value){
    this.setState({todoList: this.state.todoList.concat(value)});
  }
  render(){
      return(
          <div>
            <Form onSubmit={this.handleAdd}/>
            <TodoList todoList={this.state.todoList}/>
          </div>
      );
  }
}

export default App;

propsで状態ををバケツリレーしているイメージですね。
コンポーネントの分け方はいろいろな分け方できるので状況に応じてコンポーネントの切り分けをしてください。
例)今回はtodoListとFormで分けましたが、TodoListをさらにtodoとListに分けることやFormをさらにTextBoxとButtonのコンポーネントとして分けることもできます。

それではReact練習として今作成したTodoアプリにtodoの削除機能をつけてみてください。
ヒント 1:各Todoに削除ボタンを作り、onClickメソッドに削除機能をを入れます。
ヒント 2:TodoListの各Todoに削除で使う為のidを追加します。

答え:
下記のように各ファイルを変更します。

components/TodoList.jsx
import React from 'react';

class TodoList extends React.Component {
    handleDelete = e => {
        const id = e.target.value;
        const {onDelete} = this.props;
        onDelete(id);
    }
    render() {
        const {todoList} = this.props 
        return (
        <div>
                <ul>
                {todoList.map(
                    (item) => {
                    return<li key={item.id}>{item.content}<button value={item.id} onClick={this.handleDelete}>削除</button></li>
                    }
                )}
                </ul>
        </div>
        )
    }
}

export default TodoList;
App.jsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/Todo'
import Form from './components/Form';
import TodoList from './components/TodoList';

class App extends React.Component {
  constructor(props){
    super();
    this.state = {
        id: 3,
        todoList: [{id: 1, content: "React勉強"},{id: 2, content: "todoアプリ作成"}],
    }
    this.handleAdd = this.handleAdd.bind(this);
  }
  handleAdd(value){
    this.setState({todoList: this.state.todoList.concat({id: this.state.id, content: value})});
    this.state.id++;
  }
  handleClickDelete = id => {
    console.log(id);
    this.setState({ todoList: this.state.todoList.filter(todo => todo.id != id) });
  };
  render(){
    
      return(
          <div>
            <Form onSubmit={this.handleAdd}/>
            <TodoList todoList={this.state.todoList} onDelete={this.handleClickDelete}/>
          </div>
      );
  }
}

export default App;

結果
image.png

これで第2章は終わりです。
次回は第三章 ~Reactでhooksを使おう~です。第三章以降はfunction記法で説明していきます。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?