LoginSignup
63
66

More than 5 years have passed since last update.

NEXT.jsとReact Hooksを使ってTodoアプリを10分で作る

Last updated at Posted at 2019-05-06

Reactのフレームワークであり、かつ爆速でReact環境を構築できるNEXT.jsを使って、定番のTodoアプリを作ってみます。

そこにReact Hooksを使えばTodoアプリくらいなら10分もあれば作れるので、NEXT.jsまたはReact Hooksを使った事のない方は、気軽に取り組んでみてください。

作るもの

こんな感じの簡単なTodoアプリを作ります。
next-react-app.gif

環境設定

NEXT.jsが動く環境を作ります。

まずはプロジェクトの作成。

$ mkdir next-todo-app
$ cd next-todo-app
$ npm init -y

次にNEXT.jsおよびReactを入れる。

$npm install --save react react-dom next

そこに pages/index.jsx を作成して、以下のReactコンポーネントのコードを書きます。

pages/index.jsx
const App = () => {
  return <h1>Hello World!</h1>;
};

export default App;

package.json のscriptsも書き換えます。

package.json
"scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
}

あとは、nextを起動させて、http://localhost:3000 でHello Worldが表示されているのを確認できれば完了です。

$ npm run dev

Todoアプリを作る

NEXT.jsで一瞬でReact環境を作ることができたので、次にTodoアプリを実装していきます。

Todoアプリの基本的なコードは以下の通り

pages/index.tsx
import { useState } from "react";

const App = () => {
  // 作成したtodoを入れておくためのstate
  const [todos, setTodos] = useState([]);
  // フォームに入力された値をtodoに登録するまでに入れておくためのstate
  const [tmpTodo, setTmpTodo] = useState("");

  const addTodo = () => {
    setTodos([...todos, tmpTodo]);
    setTmpTodo("");
  };

  return (
    <>
      <h1>Todo App</h1>
      <div className="form">
        <input
          type="text"
          name="todo"
          // formの入力値をtmpTodoで持っておく
          onChange={e => setTmpTodo(e.target.value)}
          value={tmpTodo}
        />
        <button onClick={addTodo}>Add</button>
      </div>
      <ul>
        {todos.map((todo, index) => {
          return <li key={index}>{todo}</li>;
        })}
      </ul>
      <style>{`
        h1 {
          text-align: center;
        }
        .form {
          display: flex;
          justify-content: center;
        }
        ul {
          width: 200px;
          margin: 10px auto;
        }
      `}</style>
    </>
  );
};

export default App;

これで、Todoアプリに登録する処理が書けました。
React Hooksの1つであるuseStateを使うことで、stateの管理が一気に楽になります。

あとは、空白の状態でTodoが登録されないようにしつつ、削除処理のコードを加えて、Todoアプリは完成です。

pages/index.tsx
import { useState } from "react";

const App = () => {
  const [todos, setTodos] = useState([]);
  const [tmpTodo, setTmpTodo] = useState("");

  const addTodo = () => {
    // formの内容が空白の場合はalertを出す
    if (tmpTodo === "") {
      alert("文字を入力してください");
      return;
    }
    setTodos([...todos, tmpTodo]);
    setTmpTodo("");
  };

  // todoを削除する処理
  const deleteTodo = index => {
    const newTodos = todos.filter((todo, todoIndex) => {
      return index !== todoIndex;
    });
    setTodos(newTodos);
  };

  return (
    <>
      <h1>Todo App</h1>
      <div className="form">
        <input
          type="text"
          name="todo"
          onChange={e => setTmpTodo(e.target.value)}
          value={tmpTodo}
        />
        <button onClick={addTodo}>Add</button>
      </div>
      <ul>
        {todos.map((todo, index) => {
          return (
            <li key={index}>
              {todo}
              {/* 削除ボタンを追加 */}
              <button onClick={() => deleteTodo(index)}>x</button>
            </li>
          );
        })}
      </ul>
      <style>{`
        h1 {
          text-align: center;
        }
        .form {
          display: flex;
          justify-content: center;
        }
        ul {
          width: 200px;
          margin: 10px auto;
        }
      `}</style>
    </>
  );
};

export default App;

NEXT.jsを使ってReact環境の構築が簡単になったこと、React Hooksを使ってStateの管理が簡単になったことで、Todoアプリくらいなら10分くらいで作ることができるようになりました。

他にもNEXT.jsを使うことで、

  • デフォルトでサーバーサイドレンダリングされる
  • デフォルトでコードスプリッティングされる
  • デフォルトでSPAになっている
  • ページごとのシンプルなページルーティング

などの利点があります。

まあ、複雑なことをやろうとすると厳しいところもあるNEXT.jsですが、Reactの環境構築としては秀逸なので触ってみる価値はあると思います。

今回作ったコードはこちらから
https://github.com/hiraike32/next-todo-app

63
66
1

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
63
66