この記事は「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」の 3 日目の記事です。
React でフォームを実装したときにいきなりハマった点を共有したいと思います。
環境
$ node --version
v14.15.0
{
...
"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
イベントを入れないと「入力しても反映されない」現象が起きます。
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
がバインドされていない状態になってエラーになります。
アロー関数で書いてみると次の通りになります。
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