はじめに
React
の勉強したメモを備忘録の意味合いも兼ねて残しておきます。
先に言っておくと人に見せるようではないので超みづらいです。
JSXに式(値)を埋め込む
import React from 'react'; import ReactDOM from 'react-dom'; const SampleElement = () => { const dates = [{key: "1", value: "あたい", hoge: 10000}] return ( <div> <h1>一覧</h1> <table> <thead> <tr><th>Key</th><th>Value</th><th>Hoge</th></tr> </thead> <tbody> <tr><td>{dates[0].key}</td><td>{dates[0].value}</td><td>{dates[0].hoge}</td></tr> </tbody> </table> </div> ) } ReactDOM.render( <SampleElement />, document.getElementById('root') )
コンポーネントの分割とProps
import React from 'react'; import ReactDOM from 'react-dom'; // コンポーネントに渡す引数をチェックしてくれるモジュール import PropTypes from 'prop-types' const SampleElement = () => { const dates = [ {key: "1", value: "あたい", hoge: 10000} ] return ( <div> <h1>一覧</h1> <table> <thead> <tr><th>Key</th><th>Value</th><th>Hoge</th></tr> </thead> <tbody> {/* パラメーターを渡す */} <SampleItem date={dates[0]} /> </tbody> </table> </div> ) } // パラメーターをpropsで受け取り const SampleItem = (props) => { const {key, value, hoge} = props.date if(hoge > 0){ return ( <tr> <td>{key}</td> <td>{value}</td> <td>{hoge}</td> </tr> ) } else { return ( <h1>hoge : {hoge}</h1> ) } } // SampleItemコンポーネントに渡すパラメータの型を宣言 // dataというobject型が渡ってくる // isRequiredが付くと、dataパラメーターを渡さないとエラーになる SampleItem.propTypes = { date: PropTypes.object.isRequired } ReactDOM.render( <SampleElement />, document.getElementById('root') )
Props
はコンポーネント呼び出し側で設定した値の受け取り専用でコンポーネントの中で変更してはダメです。
条件演算子
const SampleItem = (props) => { const {key, value, hoge} = props.date return ( <tr> <td>{key}</td> <td>{value}</td> <td>{hoge > 0 ? hoge : 0}</td> </tr> ) }
繰り返し
key
にはユニークな値を格納します。
const SampleElement = () => { const dates = [ {key: "1", value: "あたい", hoge: 10000}, {key: "2", value: "あたい", hoge: 10000}, {key: "3", value: "あたい", hoge: 10000}, {key: "4", value: "あたい", hoge: 10000}, {key: "5", value: "あたい", hoge: 10000} ] return ( <div> <h1>一覧</h1> <table> <thead> <tr><th>Key</th><th>Value</th><th>Hoge</th></tr> </thead> <tbody> {/* 繰り返し, keyはユニークな値を入れる */} {dates.map((date) => <SampleItem date={date} key={date.key}/> )} </tbody> </table> </div> ) }
PropType
よく使いそうなもの。
型 | PropType |
---|---|
配列 | PropTypes.array |
論理値 | PropTypes.bool |
関数 | PropTypes.func |
数値 | PropTypes.number |
オブジェクト | PropTypes.object |
文字列 | PropTypes.string |
必須パラメーターの場合は.isRequired
をつける。
コンポーネント作成
コンポーネントの作成には以下の2通りあります。
Component
クラスを継承したクラス- 関数のコンポーネント
Component
クラスを継承するクラスにrender()
を定義すると、JSX
を表示することができます。
class SampleComponent extends Component{ render(){ return ( <div> <h1>サンプル</h1> </div> ) } }
Component
クラスは以下によって宣言されています。
import React, { Component } from 'react'
State
コンポーネント自体が状態や値を保ちたいとき、保存するのがState
です。
参照するときはthis.state
で、更新・代入をするときはthis.setState()
を利用します。
class SampleComponent extends Component{ constructor(){ super() this.state = {hoge: 1, fuga: "value"} } set(){ this.setState({hoge: this.state.hoge + 1, fuga: "value"}) } render(){ return ( <div> <h1>サンプル {this.state.hoge} {this.state.fuga}</h1> <button onClick={() => this.set()}>ボタン</button> </div> ) } }
コンストラクターでprops
を受け取るバージョンもあります。
class SampleConponent extends Component { constructor(props) { super(props) // 何か初期化処理 }
render()
メソッドが呼び出されるのは以下の3つの場合です。
- ブラウザにロードされた直後 (
componentDidMount()
が呼ばれる) - コンポーネントの
Props
が変更されたとき (componentWillReceiveProps()
が呼ばれる) - コンポーネント内で
setState()
が実行され、State
が変更されたとき
Controlled Components
イベント処理を使いプログラムで入力を管理するControlled Components
方式。
input
タグのonChange
属性を使い、入力されたデータを取得- 入力された値は基本的には
State
に保存 input
タグのvalue
属性はState
の値を設定
class SampleComponent extends Component{ constructor(){ super() this.state = {date: ''} } onChangeValue(event){ this.setState({[event.target.name] : event.target.value}) } render(){ return ( <div> <p>{this.state.date}</p> <input type = "text" value={this.state.date} onChange={(event) => this.setState({date: event.target.value})} /> <input type = "text" value={this.state.date} name="date" onChange={(e) => this.onChangeValue(e)} /> </div> ) } }
Uncontrolled Components
- 値を取得する必要があるタグに
ref
属性を設定し、タグをアクセスするためのインスタンス変数に設定 - 値を取得するには、上で保存したインスタンス変数を使い取得
class SampleComponent extends Component{ constructor(){ super() this.input = React.createRef() } onClickButton(){ alert(this.input.current.value) } render(){ return ( <div> <input type="text" ref={this.input} /> <button onClick={this.onClickButton}>Submit</button> </div> ) } }
フォーム要素
テキストエリア
class SampleComponent extends Component{ constructor(props){ super(props) this.state = {item: ''} } onChangeValue(event){ this.setState({[event.target.name] : event.target.value}) } render(){ return ( <div> <p>{this.state.date}</p> <textarea value={this.state.item} name="item" onChange={(e) => this.onChangeValue(e)} /> </div> ) } }
セレクトボックス
選択肢が2個バージョン。
class SampleComponent extends Component{ constructor(props){ super(props) this.state = {isSelected : false} } render(){ return ( <div> <p>{this.state.isSelected ? "ON" : "OFF"}</p> <select value={this.state.isSelected ? "on" : "off"} onChange={(e) => this.setState({isSelected: e.target.value == "on"})}> <option value="on">ON</option> <option value="off">OFF</option> </select> </div> ) } }
配布されているReactコンポーネント
Material-UI
Material-UI
はMaterial Design
に準拠したUIコンポーネントです。
Material UI is a library of React UI components that implements Google's Material Design.
Material UIは、GoogleのMaterial Designを実装したReact UIコンポーネントのライブラリです。
インストールは以下のコマンドを打ちます。
$ npm install @mui/material @emotion/react @emotion/styled
import React, { Component } from 'react' import ReactDOM from 'react-dom' // Material-UI import Button from '@mui/material/Button'; class SampleComponent extends Component{ constructor(props){ super(props) } render(){ return ( <div> <Button>text</Button> <Button variant="contained">contained</Button> <Button variant="outlined">outlined</Button> </div> ) } } ReactDOM.render( <SampleComponent />, document.getElementById('root') )
簡単にいい感じの見た目を作ることができました。詳細は公式ドキュメントを参照。
mui.com
ルーティング
ルーティング対応する方法は以下の2種類あります。
pushState()
メソッドを利用する。- URLのハッシュ(フラグメント, URLの
#
以降)に仮想的なURLを書く
React Router
インストール方法。
$ npm install react-router-dom
import React, { Component } from 'react' import ReactDOM from 'react-dom' import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'; class SampleComponent extends Component{ constructor(props){ super(props) } render(){ return ( <div> <Link to="/">Home</Link> <Link to="/hoge">Hoge</Link> <Link to="/fuga">Fuga</Link> <Routes> <Route path="/" element={<Home />} /> <Route path="/hoge" element={<Hoge />} /> <Route path="/fuga" element={<Fuga />} /> <Route path="*" element={<NoMatch />} /> </Routes> </div> ) } } const Home = () => { return ( <div> <p>Home</p> </div> ) } const Hoge = () => { return ( <div> <p>Hoge</p> </div> ) } const Fuga = () => { return ( <div> <p>Fuga</p> </div> ) } const NoMatch = () =>{ return ( <h2>このページは存在しません</h2> ) } ReactDOM.render( <BrowserRouter> <SampleComponent /> </BrowserRouter>, document.getElementById('root') )
Fetch API
フェッチ API は(ネットワーク越しの通信を含む)リソース取得のためのインターフェイスを提供しています。 XMLHttpRequest と似たものではありますが、より強力で柔軟な操作が可能です。
class SampleComponent extends Component{ constructor(props){ super(props) } onClickButton(){ // 犬の画像のURLが返ってくる fetch('https://dog.ceo/api/breeds/image/random') .then((response) => response.json()) .then((json) => alert(json.message)) } render(){ return ( <div> <button onClick={this.onClickButton}>Execute</button> </div> ) } }
ユニットテスト
Mocha
Mocha
&Node.js
に標準で入っているassert
を使ってユニットテストをします。
インストール。
$ npm install mocha --save-dev $ npm install babel-register --save-dev
package.json
に以下を追加します。
"scripts": { ... "test": "mocha --compilers js:babel-register --timeout 5000" },
--compilers js:babel-register
:テストコードはbabel
を利用する--timeout 5000
:強制終了時間をms
指定。デフォルトは2000
。
it(説明文字列, テストコードの無名関数)
のように指定します。
import assert from 'assert' it("1+1=2", () => { assert.equal(1 + 1, 2) })
グループ化にはdescribe
を利用します。
import assert from 'assert' describe('四則演算', () => { it("1+1=2", () => { assert.equal(1 + 1, 2) }) it("1+2=3", () => { assert.equal(1 + 2, 3) }) })