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

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

ただいまの
回答率

88.78%

[React]シンプルなTodoアプリを作成中。formからデータが受け取れず困っています。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 984

uk_63

score 29

実現したいこと

質問を見て下さってありがとうございます。

formからデータを受け取って、配列に追加、setStateして、一覧表示したいです。

問題

formから取得できるはずのデータが取得できず、undefinedになってしまいます。console.log(event.target.value)が未定義に....

実際のコード

練習で作っているので、一つのファイルにまとめて書いています。
見やすいようにコメントをつけました。

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

// form - ここにstateをもたせるべきか
class TodoInput extends React.Component {
  render() {
    return (
      <>
        <input name="title" type="text" placeholder="タイトルを入力" />
        <br />
        <textarea name="description" type="text" placeholder="内容を入力" />
        <br />
        <button onClick={this.props.handleSubmit}>追加</button>
      </>
    );
  }
}

// todoの一つの要素を表すコンポーネント
const TodoItem = props => {
  return (
    <>
      <li>{props.title}</li>
      <li>{props.description}</li>
    </>
  );
};

// データを受けて一覧表示させている
class TodoList extends React.Component {
  render() {
    const list = this.props.tasks.map(task => {
      return <TodoItem {...task} key={task.id} />;
    });
    return (
      <>
        <ul>{list}</ul>
      </>
    );
  }
}

// 親コンポーネント、stateをここに固めたい。
// formで入力した情報をクリックしたらsetStateしたい。
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      tasks: [],
      uniqueId: 1
    };
  }

  handleClick(e) {
    // 入力情報がeventに反映されていない
    const newTitle = e.target.title.value;
    const newDescription = e.target.description.value;
    const newUniqueId = this.state.uniqueId + 1;
    const newTasks = this.state.tasks.slice();

    newTasks.push({
      title: newTitle,
      description: newDescription,
      id: newUniqueId
    });

    this.setState({ newTasks });

    e.target.title.value = "";
    e.target.description.value = "";
  }

  resetTodo = () => {
    this.setState({
      tasks: []
    });
  };

  render() {
    return (
      <>
        <p>Todo App</p>
        <button onClick={this.resetTodo}>一括削除</button>
        <br />
        <TodoInput handleSubmit={this.handleClick.bind(this)} />
        <TodoList tasks={this.state.tasks} />
      </>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

どうかご回答お願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+3

こんにちは。

いくつかの点で修正したソースを以下に回答します。

主となる修正は、ご質問のタイトルにある、「formからデータが受け取れず困っています。」 に対して、

  • App の this.state にフォームから入力された値を持たせ、これを変更するメソッドを追加し、<input /> および <textarea /> の onChangeハンドラに設定

したことです。以下、修正後のソースです。

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

// 新規Todo入力フォーム
const TodoInput = ({ title, description, handleChange, handleSubmit }) => (
  <>
    <input
      name="title"
      type="text"
      placeholder="タイトルを入力"
      value={title}
      onChange={handleChange}
    />
    <br />
    <textarea
      name="description"
      placeholder="内容を入力"
      value={description}
      onChange={handleChange}
    />
    <br />
    <button onClick={handleSubmit}>追加</button>
  </>
);

// todoの一つの要素を表すコンポーネント
const TodoItem = ({ title, description }) => (
  <>
    <li>{title}</li>
    <li>{description}</li>
  </>
);

// データを受けて一覧表示させている
const TodoList = ({ tasks }) => (
  <ul>{tasks.map(task => <TodoItem {...task} key={task.id} />)}</ul>
);

// 親コンポーネント、stateをここに固めたい。
// formで入力した情報をクリックしたらsetStateしたい。
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: [],
      uniqueId: 1,
      form: { title: "", description: "" },
    };
  }

  handleChange = (e) => {
    this.setState({
      form: { ...this.state.form, [e.target.name]: e.target.value },
    });
  };

  handleClick = () => {
    const newTask = {
      ...this.state.form,
      id: this.state.uniqueId,
    };
    this.setState({
      tasks: [newTask, ...this.state.tasks],
      uniqueId: this.state.uniqueId + 1,
      form: { title: "", description: "" },
    });
  };

  resetTodo = () => {
    this.setState({
      tasks: []
    });
  };

  render() {
    return (
      <>
        <p>Todo App</p>
        <button onClick={this.resetTodo}>一括削除</button>
        <br />
        <TodoInput
          {...this.state.form}
          handleChange={this.handleChange}
          handleSubmit={this.handleClick}
        />
        <TodoList tasks={this.state.tasks} />
      </>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

上記のコードを含むレポジトリを以下に上げています。

上記のレポジトリは以下のコミットを古い順に含みます。

以下の画像は、修正後のものを起動してブラウザに表示させ、2つTodoを追加した後、3つ目を入力中の画面キャプチャです。

イメージ説明

以上、参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/07 09:06

    丁寧な回答ありがとうございます。
    ひとつ前の質問にも答えてくださった本当に助かりました。
    解説もわかりやすく非常に参考になります。

    ありがとうございました!

    キャンセル

  • 2019/01/07 09:58

    どういたしまして。お役に立てましたようで、よかったです👍

    キャンセル

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

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

関連した質問

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