1 minute read

学んだこと

TODO アプリ作成

  • メイン処理
    • 各処理(登録・削除・完了に遷移)をコンポーネント化。
    • 一部 Style をコンポーネント内で定義。
    • バニラ JS と異なり、全体的にコーディング量は少なめに実装できた。
import { useState } from 'react';
import './App.css';
import { InputTodo } from './components/InputTodo';
import { InCompleteTodos } from './components/IncompleteTodo';
import { CompleteTodos } from './components/CompleteTodos';

export const Todo = () => {
  const [incompleteTodos, setIncompleteTodos] = useState([]);
  const [completeTodos, setcompleteTodos] = useState([]);
  const [todoText, setTodoText] = useState('');

  const onChangeTodoText = (event) => setTodoText(event.target.value);

  const onClickAdd = () => {
    if (todoText === '') return;
    const newTodos = [...incompleteTodos, todoText];
    setIncompleteTodos(newTodos);
    setTodoText('');
  };

  const onClickDelete = (index) => {
    const newTodos = [...incompleteTodos];
    newTodos.splice(index, 1);
    setIncompleteTodos(newTodos);
  };

  const onClickComplete = (index) => {
    const newInCompleteTodos = [...incompleteTodos];
    newInCompleteTodos.splice(index, 1);

    const newCompleteTodos = [...completeTodos, incompleteTodos[index]];
    setIncompleteTodos(newInCompleteTodos);
    setcompleteTodos(newCompleteTodos);
  };

  const onClickBack = (index) => {
    const newCompleteTodos = [...completeTodos];
    newCompleteTodos.splice(index, 1);

    const newInCompleteTodos = [...incompleteTodos, completeTodos[index]];
    setcompleteTodos(newCompleteTodos);
    setIncompleteTodos(newInCompleteTodos);
  };

  const isMaxLimitCompleteTodos = incompleteTodos.length >= 5;

  return (
    <>
      <InputTodo
        todoText={todoText}
        onChange={onChangeTodoText}
        onClick={onClickAdd}
        disabled={isMaxLimitCompleteTodos}
      />
      {isMaxLimitCompleteTodos && (
        <p style=>登録できるTODOの上限は5個です。</p>
      )}
      <InCompleteTodos
        todos={incompleteTodos}
        onClickComplete={onClickComplete}
        onClickDelete={onClickDelete}
      />
      <CompleteTodos todos={completeTodos} onClickBack={onClickBack} />
    </>
  );
};

  • InComplete コンポーネント
export const InCompleteTodos = (props) => {
  const { todos, onClickComplete, onClickDelete } = props;
  return (
    <div className="incomplete-area">
      <p className="title">未完了のTODO</p>
      <ul>
        {todos.map((todo, index) => (
          <li key={todo}>
            <div class="list-row">
              <p class="list-item">{todo}</p>
              <button onClick={() => onClickComplete(index)}>完了</button>
              <button onClick={() => onClickDelete(index)}>削除</button>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
};

  • Complete コンポーネント
export const CompleteTodos = (props) => {
  const { todos, onClickBack } = props;
  return (
    <div className="complete-area">
      <p className="title">完了のTODO</p>
      <ul>
        {todos.map((todo, index) => (
          <li key={todo}>
            <div class="list-row">
              <p class="list-item">{todo}</p>
              <button onClick={() => onClickBack(index)}>戻す</button>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
};

  • InputTODO コンポーネント
    • コンポーネント内にスタイルを実装、このコンポーネントに関連するスタイルを集約するのは修正する際に楽にはなりそう。
    • 条件でボタンやインプットを制限するように実装した。
const style = {
  backgroundColor: '#c6e5d9',
  width: '400px',
  height: '30px',
  padding: '8px',
  margin: '8px',
  borderRadius: '8px',
};

export const InputTodo = (props) => {
  const { todoText, onChange, onClick, disabled } = props;
  return (
    <div style={style}>
      <input
        disabled={disabled}
        placeholder="TODOを入力"
        value={todoText}
        onChange={onChange}
      />
      <button disabled={disabled} onClick={onClick}>
        追加
      </button>
    </div>
  );
};

実際に実装してみた感想

  • バニラ JS より実装量も少なく、実装しやすかった。
  • React 独自の記法やルールはまだなれない。特にステートによる再レンダリングが起き処理が再度呼ばれてしまうというのを把握できずにバグを起こしそう。
  • props が C#や C++と比べて自由度が高く、コンポーネントの宣言時に props で使う変数を宣言せずに動作できるのは便利だと思った。
  • コンポーネント内で分割代入を行って props を省略してかけるのは良いが、props のプロパティなのかコンポーネント内で定義した変数なのか分からなくならないか心配。