0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[React][L4] リストの項目をボタンで削除する

Posted at

実施条件

[React][L3] テキストボックスの内容を出力するを理解していること

環境

MacBook Pro (2.3 GHz 8コアIntel Core i9)
macOS 14.0(23A344)
Homebrew 4.3.8
gh 2.52.0

ソースコードの前に

フォルダ構成

folda_structure
├── package.json
├── public/
│   └── index.html
├── src/
│   ├── index.jsx
│   ├── Todo.jsx
│   └── styles.css
│  

index.html

index.html
<!DOCTYPE html>
<html lang="en">
  <head> </head>

  <body>
    <div id="root"></div>
  </body>
</html>

index.jsx

index.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import { Todo } from "./Todo";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <Todo />
  </StrictMode>
);

ソースコード

Todo.jsx(旧)

Todo.jsx
import { useState } from "react";
import "./styles.css";

export const Todo = () => {

  const [todoText, setTodoText] = useState("");
  const [incompleteTodos, setIncompleteTodos] = useState([
    "TODOです1",
    "TODOです2",
  ]);
  const [completeTodos, setCompleteTodos] = useState([
    "TODOでした1",
    "TODOでした2",
  ]);

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

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

  return (
    <>
      <div className="input-area">
        <input placeholder="TODOを入力"></input>
        <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText}></input>
        <button>追加</button>
        <button onClick={onClickAdd}>追加</button>
      </div>
      <div className="incomplete-area">
        <p className="title">未完了のTODO</p>
        <ul>
          {incompleteTodos.map((todo) => {
            return (
              <li key={todo}>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>完了</button>
                  <button>削除</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
      <div className="complete-area">
        <p className="title">完了のTODO</p>
        <ul>
          {completeTodos.map((todo) => {
            return (
              <li>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>戻す</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </>
  );
};

Todo.jsx

Todo.jsx
import { useState } from "react";
import "./styles.css";

export const Todo = () => {
  const [todoText, setTodoText] = useState("");
  const [incompleteTodos, setIncompleteTodos] = useState([
    "TODOです1",
    "TODOです2",
  ]);
  const [completeTodos, setCompleteTodos] = useState([
    "TODOでした1",
    "TODOでした2",
  ]);

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

  const onClickAdd = () => {
    if (todoText === "") {
      return;
    } else {
      const newTodos = [...incompleteTodos, todoText];
      setIncompleteTodos(newTodos);
      setTodoText("");
    }
  };
+  const onClickDelete = (index) => {
+   const newTodos = [...incompleteTodos];
+   newTodos.splice(index, 1);
+   setIncompleteTodos(newTodos);
+ };

  return (
    <>
      <div className="input-area">
        <input
          placeholder="TODOを入力"
          value={todoText}
          onChange={onChangeTodoText}
        ></input>
        <button onClick={onClickAdd}>追加</button>
      </div>
      <div className="incomplete-area">
        <p className="title">未完了のTODO</p>
        <ul>
-         {incompleteTodos.map((todo) => {        
+         {incompleteTodos.map((todo, index) => {
            return (
              <li key={todo}>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>完了</button>
-                 <button>削除</button>
+                 <button onClick={() => onClickDelete(index)}>削除</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
      <div className="complete-area">
        <p className="title">完了のTODO</p>
        <ul>
          {completeTodos.map((todo) => {
            return (
              <li>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>戻す</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </>
  );
};

解説

目的

  • buttonタグ(削除)を押下した時に、配列incompleteTodosの任意の要素を削除する

コーディング

  1. buttonタグ(削除)を押下した際に発火する、onClickイベントを設定する

    Todo.jsx
    -                 <button>削除</button>
    +                 <button onClick={onClickDelete)}>削除</button>
    
  2. onClickイベントで呼び出される関数をonClickDeleteとして設定する

    Todo.jsx
    +  const onClickDelete = () => {
    + };
    
  3. 配列incompleteTodosの任意の項目を指定するには、配列incompleteTodos内の何番目の配列かを見分けられれば良い
    =配列のindexを取得する

    Todo.jsx
    -         {incompleteTodos.map((todo) => {        
    +         {incompleteTodos.map((todo, index) => {
    
  4. onClickDeleteindexを関数n引数として設定する

    Todo.jsx
    +  const onClickDelete = (index) => {
    + };
    
  5. onCkickindexを関数の引数として設定する
    なぜ、onClick={onClickDelete(index)と記載せずに、onClick={() => onClickDelete(index)と記載するかはこちらを参照

    Todo.jsx
    -                 <button>削除</button>
    +                 <button onClick={() => onClickDelete(index))}>削除</button>
    
  6. 最新のtodoTextの値を、配列incompleteTodosに追加して、newTodosとして定義する

    Todo.jsx
       const onClickDelete = (index) => {
    +   const newTodos = [...incompleteTodos];
      };
    
  7. spliceメソッドを使って、渡ってきた第一引数indexから第二引数1番目を削除する

    Todo.jsx
       const onClickDelete = (index) => {
        const newTodos = [...incompleteTodos];
    +   newTodos.splice(index, 1);
      };
    
  8. newTodosを配列incompleteTodosの更新関数であるsetIncompleteTodosに引数として渡す
    = 配列incompleteTodosを更新する

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

処理

  1. incompleteTodosに登録されているTODOがリストとして表示されている
  2. ユーザーが削除ボタンを押下する
  3. onClickイベントが発火する
  4. {incompleteTodos.map((todo, index) => {...}}によってindexが各li要素に渡されているので、該当の要素がわかる
  5. () => onClickDelete(index)が実行される
  6. 該当のindexonClickDeleteに渡る
  7. 最新の配列incompleteTodosnewTodosに渡す(コピーする)
  8. spliceメソッドを使って、newTodosの第一引数indexから第二引数1番目を削除する
  9. newTodosを更新関数setIncompleteTodosに渡す
  10. incompleteTodosが更新される
  11. Reactの再レンダリングがトリガーされる
  12. buttonタグ(削除)を押下した時に、配列incompleteTodosの任意の要素が削除される

イメージ

Todo.jsx(旧)

image.png

Todo.jsx

image.png

参考リンク

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?