0
2

More than 3 years have passed since last update.

【入力値反映されない】Reactでクラスを使ったときにフォームでハマった話【Cannot read property 'state' of undefined】

Last updated at Posted at 2020-12-04

この記事は「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」の 3 日目の記事です。

React でフォームを実装したときにいきなりハマった点を共有したいと思います。

環境

$ node --version
v14.15.0
package.json
{
...
  "dependencies": {
    "next": "10.0.3",
    "react": "17.0.1",
    "react-dom": "17.0.1"
  },
  "devDependencies": {
    "@types/node": "^14.14.10",
    "@types/react": "^17.0.0",
    "typescript": "^4.1.2"
  }
}

ちなみに私はVue(Nuxt)を使っていてReactに入門しています…!

state に紐づけたテキストボックスに入力しても反映されない

これはReactのドキュメントに書いてあるので、初めに読めば防げる問題ですが…

React で管理したいテキストボックスには handleChange 関数と onChange イベントを入れないと「入力しても反映されない」現象が起きます。

src/App.tsx
import React, { Component } from 'react';
import './App.css';

type Props = {}

type State = {
  todo: TodoItem[],
  currentText: string
}

type TodoItem = {
  title: String
}

class App extends Component<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state =  {
      todo: [
        { title: 'JavaScript覚える' },
        { title: 'jQuery覚える' },
        { title: 'ES2015覚える' },
        { title: 'React覚える' }
       ],
       currentText: ''
    }

    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(event: React.ChangeEvent<HTMLInputElement>) {
    this.setState({
      currentText: event.target.value
    })
  }

    render() {
    return (
    ...

        <input type="text" value={this.state.currentText} onChange={this.handleChange}/> <input type="button" value="追加" onClick={this.addTodo} />
      </div>
    );
  }

さらに、TypeScript で書くときはテキストボックスに入力したときの Event の型も指定します。
any にしなくても次の Event 型から使うことができます。

any 型で諦めない React.EventCallback - Qiita
https://qiita.com/Takepepe/items/f1ba99a7ca7e66290f24

クラス内の関数でstateを操作するとCannot read property 'state' of undefinedと出る

ボタンをクリックしたときにフォームで入力した値を使いたいですよね?ところがボタンをクリックしたときに次のメッセージが表示されます。

TypeError: Cannot read property 'state' of undefined

クラスの「中で」関数を書く場合、state など this から使うものは 関数をアロー関数にしないと関数が呼び出されたときに this がバインドされていない状態になってエラーになります。

アロー関数で書いてみると次の通りになります。

src/App.tsx
class App extends Component<Props, State> {

  ...
  addTodo =()=> {
    this.state.todo.push({
      title: this.state.currentText
    })

    this.setState({
      todo: this.state.todo,
      currentText: ''
    })
  }

  deleteTodo = (i: number)=> {
    this.state.todo.splice(i, 1)
    this.setState({
      todo: this.state.todo
    })
  }

  render() {
    return (
      <div>
        <h1>TODOアプリ</h1>
        <nav>
        <ul>{this.state.todo.map( (todo, i) => {
          return <li key={i}><input type="button" value="☓" onClick={() => this.deleteTodo(i)}/> {todo.title}</li>
        })}</ul>
        <input type="text" value={this.state.currentText} onChange={this.handleChange}/> <input type="button" value="追加" onClick={this.addTodo} />
      </div>
    );
  }

参考

(コードの元ネタ)
React で作る TODO アプリ前編 – React 入門 - to-R Media
https://www.to-r.net/media/react-tutorial13/

React.js で Form を扱う - Qiita
https://qiita.com/koba04/items/40cc217ab925ef651113

any 型で諦めない React.EventCallback - Qiita
https://qiita.com/Takepepe/items/f1ba99a7ca7e66290f24

「TypeError: Cannot read property ‘state’ of undefined」に出会ったら Javascript の”this”について真剣に考えよう
https://applingo.tokyo/article/1422

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