質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.77%

React CheckBoxの判定の仕方

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 2,016

score 44

チェックボックスの処理の書き方について困っています。
Listの一行目、または二行目または三行目のチェックボックスがクリックされた時そのtaskのdoneをtrueにするにはどう書いたらいいでしょうか?
どの行のチェックボックスがクリックされたかどうやったらわかるのでしょうか?

export type Task = {
    id: number
    title: string
    done: boolean
}
const App: React.FC = () => {
    const [tasks, setTasks] = useState([])

    return (
        <div>
            <TaskInput setTasks={setTasks} tasks={tasks} />
            <TaskList setTasks={setTasks} tasks={tasks} />
        </div>
    )
}
//子コンポーネント
import React from 'react'
import { Task } from './Types'

type Props = {
    task: Task
    handleDone: (task: Task) => void
    handleDelete: (task: Task) => void
}

const TaskItem: React.FC<Props> = ({ task, handleDone, handleDelete }) => {

    return (
    {task.map((i) => (
        <li>
            <label>
                <input
                    type="checkbox"
                    className="checkbox-input"
                    onClick={//チェックされたらdoneをtrueにしたい}
                />
                <span className="checkbox-label">{i.title }</span>
            </label>
            <button
                onClick={() => handleDelete(task)}
                className="btn is-delete"
            >削除</button>
        </li>
    )
}

export default TaskItem
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyabi_takatsuk

    2020/01/23 14:47

    すみません、Reactは勉強中なのですが、
    中かっこ({}です)の開始と閉じの数が合っていないようなのですが、
    それに関してエラーが出てたりしませんか?
    {task.map((i) => (
    の{に対しての、}が無いようにお見受けします。
    案外それで解決するかもですよ。

    キャンセル

  • thyda.eiqau

    2020/01/23 15:03

    task.map() していますが、task: Taskは配列ではないのでは?
    <TaskItem />をどう呼び出しているかもご提示ください。

    キャンセル

回答 1

checkベストアンサー

+1

前提がわからない (<TaskItem /> をどう呼び出しているか等) ままエスパーした箇所もあるので正確ではないかもしれないし、TypeScriptはこの質問を見て初めて書いたのでお作法が違ったりもっと良い書き方があったりするかもしれませんが、とりあえず下記で動くのは動きました。

結局やっていることはシンプルで、 onChange ハンドラでpropsで渡されたhandleDoneをコールして、handleDone側でstateの値を変更すればよいです。

これ以上の解説は前提条件がないと無理ですので適宜追記してください。

/// App.tsx

import React, { useState } from 'react';

type Task = {
  id: number
  title: string
  done: boolean
}

interface TaskListProps {
  tasks: Task[]
  handleDone: (id: number) => void
  handleDelete: (id: number) => void
}

const TaskList: React.FC<TaskListProps> = ({tasks, handleDone, handleDelete}) => {
  return (
    <div>
      {
        tasks.map(task => (
          <li key={task.id}>
            <label>
              <input
                type="checkbox"
                className="checkbox-input"
                checked={task.done}
                onChange={() => handleDone(task.id)}
              />
              <span className="checkbox-label">{task.title}</span>
            </label>
            <button
              onClick={() => handleDelete(task.id)}
              className="btn is-delete"
            >削除</button>
          </li>
        ))
      }
    </div>
  )
}

const App: React.FC = () => {
  const [tasks, setTasks] = useState<Task[]>([{
    id: 42,
    title: "The Answer",
    done: false
  }])

  const handleDone = (id: number) => {
    setTasks(tasks.map(t => {
      t.done = t.id === id? !t.done : t.done
      return t
    }))
    console.table(tasks);
  }

  const handleDelete = (id: number) => {
    setTasks(tasks.filter(t => t.id !== id))
  }

  return (
    <div className="App">
      <TaskList
        tasks={tasks}
        handleDone={handleDone}
        handleDelete={handleDelete}
      />
    </div>
  );
}

export default App;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/23 18:31

    コードカラーリングに関しては失礼しました!そうだったのですね!
    あら・・・、どうなんですかね・・・。
    私は、VS Codeで、Linter使ってるのですが、
    警告発生しているので、設定厳しすぎるのかな・・・。
    確かに、それでよさそうですね 汗
    コメント大変に失礼しました。

    キャンセル

  • 2020/01/24 10:07

    ご回答ありがとうございます。
    t.done = t.id === id? !t.done : t.doneはどういう意味なんでしょうか?

    キャンセル

  • 2020/01/24 11:14

    短縮せずに書くとこうです。
    tasks.map((t: Task) => {
    if(t.id === id) {
    t.done = !t.done;
    }
    return t;
    })
    stateの `tasks: Task[]` をmapでループして、各要素を `t: Task` に代入してアクセスしています。
    tのidが、クリックイベントの発火元になったidと一致しているなら、そのtのdoneを反転しています (done: trueのときにクリックしたらfalseになり、falseのときにクリックしたらtrueになる)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る