React学習1(Prettier+ESLint, state, computed/method)
React復習がてら要点をまとめていく。
環境構築
Starter Kit
create-react-app
をグローバルでインストールして、スターターファイルを立ち上げる。
create-react-app counter-app
ちなみに、スターター系は公式ドキュメントStarter Kits – Reactにもまとめられている。
Prettier + ESLintをStandardJSに沿ってVSCodeで設定
必要なパッケージをインストール。
yarn add -D \ eslint \ prettier \ eslint-config-prettier \ eslint-config-standard \ eslint-plugin-import \ eslint-plugin-node \ eslint-plugin-prettier \ eslint-plugin-promise \ eslint-plugin-standard
次に、VSCodeの設定ファイルであるsettings.json
に記述を追加する。
{ "eslint.autoFixOnSave": true, }
.eslintrc.json
を作成して記述を追加
{ "extends": [ "standard", "prettier" ], "rules": { "prettier/prettier": [ "error", { "singleQuote": true, "semi": false, "trailingComma": "all" } ] }, "parser": "babel-eslint", "plugins": [ "prettier" ] }
最初のコンポーネント
プラスボタンを押して、カウンターの数値が上がっていくというシンプルなコンポーネントを作る。 ゼロのときはZeroが表示されて、1以上は数値を画面表示する。次いでにリスト表示もしてみる。
- 何かを返却するファンクションに関しては
()
を末尾に付けてJSX内に記述する。 - イベントハンドラにメソッドを記述した場合は
()
は書かない。 - イベントハンドラにメソッドを記述した場合に、メソッドの書き方に応じて
this
をどうバインドさせるかというものに複数の書き方がある。- constructorを記述して書くパターン
- アローファンクションで書くパターン
state, method, listのレンダリング
Counter.jsx
(constructorを記述して書くパターン)
import React, { Component } from 'react' class Counter extends Component { state = { count: 0, tags: ['tag1', 'tag2', 'tag3'], } constructor() { super() this.handleIncrement = this.handleIncrement.bind(this) } render() { return ( <> {this.state.tags.length === 0 && 'Please create a new tag!'} {this.renderTags()} </> ) } handleIncrement() { console.log('Increment clicked!', this) this.setState({ count: this.state.count + 1, }) } renderTags() { if (this.state.tags.length === 0) return <p>There are no items!</p> return ( <> <span className={this.getBadgeClasses()}>{this.formatCount()}</span> <button onClick={this.handleIncrement} className="btn btn-secondary btn-sm" > Increment </button> <ul> {this.state.tags.map(tag => ( <li key={tag}>{tag}</li> ))} </ul> </> ) } getBadgeClasses() { let classes = 'badge m-2 badge-' classes += this.state.count === 0 ? 'warning' : 'primary' return classes } formatCount() { const { count } = this.state return count === 0 ? <h1>Zero</h1> : count } } export default Counter
Counter.jsx
(アローファンクションで書くパターン)
import React, { Component } from 'react' class Counter extends Component { state = { count: 0, tags: ['tag1', 'tag2', 'tag3'], } render() { return ( <> {this.state.tags.length === 0 && 'Please create a new tag!'} {this.renderTags()} </> ) } handleIncrement = () => { console.log('Increment clicked!', this) this.setState({ count: this.state.count + 1, }) } renderTags() { if (this.state.tags.length === 0) return <p>There are no items!</p> return ( <> <span className={this.getBadgeClasses()}>{this.formatCount()}</span> <button onClick={this.handleIncrement} className="btn btn-secondary btn-sm" > Increment </button> <ul> {this.state.tags.map(tag => ( <li key={tag}>{tag}</li> ))} </ul> </> ) } getBadgeClasses() { let classes = 'badge m-2 badge-' classes += this.state.count === 0 ? 'warning' : 'primary' return classes } formatCount() { const { count } = this.state return count === 0 ? <h1>Zero</h1> : count } } export default Counter
メソッドに引数を渡したい場合
引数を渡してイベントハンドラをJSX内に記述したい場合は、アローファンクションで記述する。
Counter.jsx
import React, { Component } from 'react' class Counter extends Component { state = { count: 0, tags: ['tag1', 'tag2', 'tag3'], product: { id: 1 }, } render() { return ( <> {this.state.tags.length === 0 && 'Please create a new tag!'} {this.renderTags()} </> ) } handleIncrement = product => { console.log(product) this.setState({ count: this.state.count + 1, }) } renderTags() { const { product } = this.state if (this.state.tags.length === 0) return <p>There are no items!</p> return ( <> <span className={this.getBadgeClasses()}>{this.formatCount()}</span> <button onClick={() => this.handleIncrement(product)} className="btn btn-secondary btn-sm" > Increment </button> <ul> {this.state.tags.map(tag => ( <li key={tag}>{tag}</li> ))} </ul> </> ) } getBadgeClasses() { let classes = 'badge m-2 badge-' classes += this.state.count === 0 ? 'warning' : 'primary' return classes } formatCount() { const { count } = this.state return count === 0 ? <h1>Zero</h1> : count } } export default Counter