Chapter 07無料公開

ステートを更新するコールバック関数を作成する

Kei Touge
Kei Touge
2021.10.23に更新

コールバック関数の作成

それでは todos ステートを更新(=新しいタスクの追加)していきましょう。
ステートを更新するコールバック関数を作成します。

src/App.tsx
  const [todos, setTodos] = useState<Todo[]>([]);

  // todos ステートを更新する関数
  const handleOnSubmit = () => {
    // 何も入力されていなかったらリターン
    if (!text) return;

    // 新しい Todo を作成
    const newTodo: Todo = {
      value: text,
    };

    /**
     * スプレッド構文を用いて todos ステートのコピーへ newTodo を追加する
     * 以下と同義
     *
     * const oldTodos = todos.slice();
     * oldTodos.unshift(newTodo);
     * setTodos(oldTodos);
     *
     **/
    setTodos([newTodo, ...todos]);
    // フォームへの入力をクリアする
    setText('');
  };

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax

コールバック関数をイベントに割り当てる

上のコールバック関数を onSubmit イベントへ紐付けましょう。

注意点:

  • コールバックとして渡すのは () => hoge() もしくは hoge関数そのものです
  • hoge() のみだと即時に実行されてしまうので用をなしません

https://sbfl.net/blog/2019/02/08/javascript-callback-func/

<form> タグの中でいったん e.preventDefault() しているのは Enter キー打鍵でページそのものがリロードされてしまうのを防ぐためです。

src/App.tsx
  return (
    <div>
     {/* コールバックとして () => handleOnSubmit() を渡す */}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          handleOnSubmit();
        }}
      >
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
        {/* 上に同じ */}
        <input type="submit" value="追加" onSubmit={handleOnSubmit} />
     </form>
   </div>

onSubmit イベントが発火するとコールバック関数が実行され、todos ステートを更新(=新しいタスクを追加)します。
フォームへ入力して submit(Enter キー打鍵)すれば、ステート (todos) が更新されていることを開発者ツールで確認できます。

2021-04-25 7.33.48 (1).png

text ステート向けのコールバック関数も用意する

上の例で要領を得ましたので、text ステート についても JSX の中で直接 setText していた部分をコールバック関数 handleOnChange() として書き出しましょう。

コールバック関数として書き出すことで、のちにコンポーネント間での props の受け渡しが容易になったことに気が付きます。

src/App.tsx
  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value);
  };
src/App.tsx
<input type="text" value={text} onChange={(e) => handleOnChange(e)} />

イベントの型を調べる

イベントの型がわからない時は、VSCode であればイベント上でマウスカーソルを hover させるとポップアップが表示されます。

この章のソースコード全文

App.tsx
src/App.tsx
import { useState } from 'react';

type Todo = {
  value: string;
};

export const App = () => {
  const [text, setText] = useState('');
  const [todos, setTodos] = useState<Todo[]>([]);

  const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value);
  };

  const handleOnSubmit = () => {
    if (!text) return;

    const newTodo: Todo = {
      value: text,
    };

    setTodos([newTodo, ...todos]);
    setText('');
  };

  return (
    <div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          handleOnSubmit();
        }}
      >
        <input type="text" value={text} onChange={(e) => handleOnChange(e)} />
        <input type="submit" value="追加" onSubmit={handleOnSubmit} />
      </form>
    </div>
  );
};