LoginSignup
21
21

More than 3 years have passed since last update.

React Hooks、関数コンポーネントを使ってみた

Last updated at Posted at 2020-04-19

関数コンポーネント、ReactHooksについて調べ、触ってみてわかったことをまとめます。

背景

  • 以前はクラスコンポーネントが主流だった
  • クラスコンポーネントはいろんなことができる故に、コードがカオスになりがち
  • 現在はより関数コンポーネントが主流
  • 関数コンポーネントとHooksを組み合わせることで、程よくReactの機能にアクセスできるようになる

注意点など

  • Hooksは全てuseHogehogeという名前
  • 必ず関数の中のトップレベルで使う
    • 要はif文やfor文の中で使ってはいけない
    • いつ何時でも、同じ回数同じ順番で実行される必要がある。
    • 基本的に関数の一番上に並べておけばOK

よく使うHooks

  • useState
    • stateの読み書きに使う
  • useEffect
    • ライフサイクルメソッドの代替

関数コンポーネント + HooksでTodoアプリを作ってみる

セットアップ

$ create-react-app react-todo
$ cd react-todo
$ rm -rf src
$ mkdir src src/components
$ cd src
$ touch index.js components/App.js components/AddTodo.js components/TodoElement.js

実装

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

コンポーネントを分割しない場合

src/components/App.js
import React, { useState } from "react";

const App = () => {
  const [value, setValue] = useState("");
  const [todoList, setTodoList] = useState([]);

  const handleChange = (e) => {
    const newValue = e.target.value;
    setValue(newValue);
  };

  const add = () => {
    const newTodo = { id: todoList.length, content: value };
    const newTodoList = [...todoList, newTodo];
    setTodoList(newTodoList);
    setValue("");
  };

  const handleDelete = (id) => {
    const newTodoList = todoList.filter((todo) => todo.id !== id);
    setTodoList(newTodoList);
  };

  return (
    <div>
      <h1>TODO App</h1>
      <input type="text" value={value} onChange={handleChange} />
      <button onClick={add}>追加</button>
      <ul>
        {todoList.map((todo) => (
          <li key={todo.id}>
            {todo.content}
            <button onClick={() => handleDelete(todo.id)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;

コンポーネントを分割する場合

src/components/App.js
import React, { useState } from "react";
import TodoElement from "./TodoElement";
import AddTodo from "./AddTodo";

const App = () => {
  const [value, setValue] = useState("");
  const [todoList, setTodoList] = useState([]);

  const handleChange = (e) => {
    const newValue = e.target.value;
    setValue(newValue);
  };

  const add = () => {
    const newTodo = { id: todoList.length, content: value };
    const newTodoList = [...todoList, newTodo];
    setTodoList(newTodoList);
    setValue("");
  };

  const handleDelete = (id) => {
    const newTodoList = todoList.filter((todo) => todo.id !== id);
    setTodoList(newTodoList);
  };

  return (
    <div>
      <h1>TODO App</h1>
      <AddTodo value={value} onChange={handleChange} add={add} />
      <ul>
        {todoList.map((todo) => (
          <TodoElement
            key={todo.id}
            content={todo.content}
            onDelete={() => handleDelete(todo.id)}
          />
        ))}
      </ul>
    </div>
  );
};

export default App;
src/components/AddTodo.js
import React from "react";

const AddTodo = (props) => {
  return (
    <>
      <input type="text" value={props.value} onChange={props.onChange} />
      <button onClick={props.add}>追加</button>
    </>
  );
};

export default AddTodo;
src/components/TodoElement.js
import React from "react";

const TodoElement = (props) => {
  return (
    <li>
      {props.content}
      <button onClick={props.onDelete}>削除</button>
    </li>
  );
};

export default TodoElement;

ポイント

  • render関数はpureな関数であるべき
    • stateの変更が起こるとrender関数が呼ばれるようになっているので無限ループになってしまう
    • render関数内でstateを変更してはいけない
  • 関数コンポーネントで実装すると、thisを使って内部のメソッドや変数にアクセスする必要がないので、thisの挙動を意識せずに済む
  • onChangeなどのイベントハンドラでは、関数を渡すと引数も勝手に渡してくれる
  • stateはできるだけ一箇所で管理する
    • 子コンポーネント内で変更があったときはpropsの関数を実行して親で処理を行う
  • propsはon〇〇という名前が一般的なのに対して、そのコールバック関数はhandle〇〇という名前が一般的

参考

21
21
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
21
21