Kindle本「速習React」のまとめ。
点数
93点
感想
とてもわかりやすかった。
JSX、コンポーネント、イベント、ルーティング、などReactを使う際に最低限必要な説明はすべて網羅されていたと思う。
まとめ
JSX
- 全体を1つのルート要素で囲む。
- ルート要素を最終的な出力に含めたくない場合は
<React.Fragment>
で囲む。 - タグは必ず閉じる。(img, inputなど空要素のタグは/>が必要)
- class属性⇒className、for属性⇒htmlFor、とする。
- onkeyup⇒onKeyUp、tabindex⇒tabIndexのように、2語以上の属性名はキャメルケースにする。
- HTMLコメント
<!-- -->
は使えない、{}
内でjavaScriptコメント/* */
を使う。 - 属性値にクォートを付けてはいけない。
{}
内はHTMLエスケープされる。HTMLを有効にしたい場合は、オブジェクトの__htmlキーに文字列をセットし、dangerouslySetInnerHTML属性に指定する。- タグボディにはテキストまたはReactコンポーネントを渡すことができ、コンポーネント内では
this.props.children
で取得できる。 - 繰り返し処理には配列のmapメソッドを使う。
その他
- Reactではコンボボックス、テキストエリアの値はvalue属性が使われる
- チェックボックスはchecked属性を
checked={this.state.xxx === 値}
とする。 - 通常はすべての出力はコンポーネントで生成するので、ReactDOM.renderメソッドはルートコンポーネントを呼び出すためだけに使われる。
- Reactではfalseを返してもデフォルトイベントを抑止しないため、明示的にpreventDefaultを呼び出す必要がある。
- setStateによるstateの書き換えは非同期処理である。
- SyntheticEventはプーリングされるため、非同期処理で参照することはできない。
- stateを更新するメソッドをpropsとして子コンポーネントに渡すことで、子から親への情報伝達が可能となる。
基本
インストール
- CDN
- npm
- create-react-app
1は実行時にトランスコンパイルされるため、低速になるので非実用的。学習用と考えてよい。
2はnpmコマンドで必要なツールのみをインストールする方法。
本格的に開発するならば、3がお勧め。本書でも採用している。
create-react-appはNode.js上で動くコマンドラインツール。必要なライブラリ、ビルドツール(webpack, Babel)、開発サーバまでまとめて用意してくれる。
CDNを使用しての実行
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
<script type="text/babel">
ReactDOM.render(<h1>hello</h1>, document.getElementById('root'));
</script>
※本番環境では、reactとreact-domのdevelopment.jsをproduction.min.jsとする
scriptタグのcrossorigin属性
外部スクリプト読み込み時のリクエストにクッキーや証明書を送らないことを意味する。通常はクッキーなどは不要なので、原則としてcrossorigin属性を付けるべき。crossorigin="anonymous"
としても同じ意味。
create-react-appでのアプリ作成
npm -y init
npm install --save-dev create-react-app
※2019年12月よりグローバルインストールはできなくなった。 ※TypeScriptを使う場合は–typescriptをつける。tsconfig.jsonが作成される。npx create-react-app アプリ名
※デフォルトではyarnが使用されyarn.lockが生成される。npmにしたい場合は–use-npmを付ける。
※TypeScriptを使う場合は–typescriptを付けるcd アプリ名
- 各種実行方法
npm start
:開発サーバで実行(start, stop, restartはrunを省略可能)npm run build
:/buildディレクトリに本番環境用ソースをビルドnpm run test
:テスト実行npm run eject
:webpack/babelの設定情報を出力⇒カスタマイズが必要な場合だけ行う。
※一度ejectしたら戻すことはできないので注意
strictモード
create-react-appで生成されたアプリは、<React.StrictMode>
で囲まれている。
これは開発モードの場合に様々な警告を表示してくれるものであり、本番ビルドには影響を与えない。
strictモードではconstructor, render, setStateの引数に渡した関数、が2回ずつ実行されるので注意。
https://ja.reactjs.org/docs/strict-mode.html
https://qiita.com/jkr_2255/items/b154f502d714a3b32e86
処理の流れ
public/index.html⇒src/index.js⇒src/App.js
index.html
<div id="root"></div>
がReactアプリを表示する領域=ルート要素
※scriptタグは存在しない。ビルドして生成されるHTMLにはscriptが存在する。
index.js
Reactアプリ実行時に最初に呼び出されるファイル。ReactDOM.render(<App />, document.getElementById('root'));
がアプリ本体。
※末尾のserviceWorker.unregister();
はオフラインキャッシュを無効にしている。通常はこのままでOK。
App.js
Reace16.8.6からコンポーネント定義がクラスから関数ベースに変わった。
(class App extends Component{}
だったのがfunction App() {}
に変わった)
コンポーネントで利用するCSS、画像はimport文で読み込んでおく。import './App.css';
import img1 from './img1.jpg';
※画像は、<img src="{img1}">
とするだけでインラインイメージ(バイナリのbase64)となる。
ReactDOM.renderメソッド
第1引数にコンポーネントを指定するのが基本的な使い方。ReactDOM.render(<App />, document.getElementById('root'));
通常はすべての出力はコンポーネントで生成するので、ReactDOM.renderメソッドはルートコンポーネントを呼び出すためだけに使われる。
コンポーネントではないJSXを渡すこともできるが、使うことはあまりない。ReactDOM.render(<p>hoge</p>, document.getElementById('root'));
JSX
JSXのルール
- 全体を1つのルート要素で囲む。
- ルート要素を最終的な出力に含めたくない場合は
<React.Fragment>
で囲む。
※<tr><Hoge/></tr>
のような場合、Hogeコンポーネントはreturn (<React.Fragment><th>hoge</th><td>hoge</td></React.Fragment>)
のようにする。 - img, inputなど空要素のタグは
/>
が必要。(HTML5の記述は×、XHTMLの記述は○) - class属性⇒className、for属性⇒htmlFor、にする。(JavaScriptの予約語であるため)
- onclick⇒onClick、onkeyup⇒onKeyUp、tabindex⇒tabIndexのように、2語以上の属性名はキャメルケースにする。
- HTMLコメント
<!-- -->
は使えない、{}
内でjavaScriptコメント/* */
を使う。<p>test{/* コメント */}</p>
- 属性値にクォートを付けてはいけない。
<a href={url}>
※クォートで括った場合は文字列として扱われる。 - style属性にはオブジェクトを渡す。(キーはキャメル形式)
<p style={{ backgroundColor: 'red' }}>
{}でJSXにJavaScript式を埋め込む
const itemName = 'リンゴ<br>です。';
function MyList() {
return (
<p>{itemName}</p>
);
}
{}
内はHTMLエスケープされる。 HTMLを有効にしたい場合は、オブジェクトの__htmlプロパティに文字列をセットし、dangerouslySetInnerHTML属性に指定する。 <p dangerouslySetInnerHTML={{ __html: "リンゴ<br>です。" }}></p>
※dangerouslySetInnerHTML属性を指定した場合、空要素にしないとエラーになる
// React要素の配列を渡すこともできる。ループ処理でよく使われる。
function MyList() {
return (
<div>{[<p>11</p>, <p>22</p>]}</div>
);
}
// これは以下と同じ意味。
function MyList() {
return (
<div>
<p>11</p>
<p>22</p>
</div>
);
}
React.createElementメソッド
JSXは内部的にはトランスパイルでReact.createElementメソッドに変換される。React.createElement(タグ, 属性, 子要素1, 子要素2, ...)
第1引数:タグ名 or コンポーネント(クラスまたは関数)
第2引数:属性の連想配列
第3引数以降:テキスト or ReactElementオブジェクト
ex)React.createElement('div', { className: 'hoge' }, 'テスト', React.createElement('h1', null, 'Hello'));
コンポーネント
コンポーネントのルール
- コンポーネントの名前はPascal形式でなければならない。
- 関数コンポーネントとクラスコンポーネントがある。
- 関数コンポーネントはpropsを引数として受け取りJSXをreturnする関数を定義する。
function App(props) {
return(<div>hoge</div>);
}
- 関数コンポーネントは「Stateの管理ができない」「ライフライクルメソッドの定義ができない」という制限がある。
- クラスコンポーネントはJSXをreturnするrenderメソッドを定義したクラスを定義する。
export default class App extends React.Component{
render() {
return (<div>hoge</div>);
}
}
著者は「関数にしてもコード量をそこまで節約できない」「記法をどちらかに統一した方が読みやすい」などからクラスコンポーネントで統一することをオススメしている。
一般的には、Stateやライフライクルメソッドを使う場合はクラス、それ以外は関数、として混在させることが多いらしい。
コンポーネントへパラメータを渡す
プロパティ(Props)を利用する。
タグの属性値は、コンポーネントクラス内ではthis.props.xxx
で取得できる。<MyList items={['apple', 'orange']}/>
という属性値は<p>{this.props.items[0]}</p>
のように取得できる。
※属性をまとめて設定する場合はオブジェクトのスプレッド構文が便利<p {...obj}>
<p hoge={obj}>
だと、参照時はthis.props.hoge.xxx
になってしまう(スプレッド構文だとthis.props.xxx
)
タグボディの取得
テキストまたはReactコンポーネントを渡すことができる。
コンポーネント内ではthis.props.children
で取得できる。
<App>hoge</App>
はthis.props.children
に文字列hoge
がセットされる。<App>{[100, 200]}</App>
はthis.props.children[0]
のように取得できる。<App><hr /></App>
とすると、<hr />
は文字列ではなくReactコンポーネントとなるので注意。
⇒<App>{"<hr />"}</App>
は文字列なので、{this.props.children}
はHTMLエスケープされる
prop-typesによるプロパティの型チェック
npm install --save-dev prop-types
でインストール
import PropTypes from 'prop-types';
// 〜省略〜
App.propTypes = {
name: PropTypes.string.isRequired,
items: PropTypes.array.isRequired,
children: PropTypes.string.isRequired,
};
- エラーはコンソールに表示される。
- クラスコンポーネントの場合は
static propTypes = {//型定義};
でも定義でき、こちらの方が可読性が上がる。
(クラスプロパティはES6では使用できないECMAScriptの実験的機能だが、create-react-appではbabelによって変換される) - 型はstring, number, bool, array, object, func, element,nodeなど。 element:React要素のこと。
node:renderできるもの。(element, numner, string, arrayのどれか) - 配列はarrayOf(PropType.型)で要素の型までチェックできる。
age: PropTypes.arrayOf(PropTypes.number),
- instanceOf(クラス名)でクラス型の指定が可能。
name: PropTypes.instanceOf(Member),
- oneOf(配列)でin_arrayチェック。要素の型までチェックされる。
age: PropTypes.oneOf(['30', 40]),
- shape(オブジェクト)でオブジェクトのプロパティの型まで指定できる。
member: PropTypes.shape({name: PropTypes.string, age: PropTypes.number})
オブジェクト配列の場合data: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired
}))
プロパティのデフォルト値
defaultPropsで定義する。
App.defaultProps = {
name: 'defaultName'
};
// クラスコンポーネントの場合はstaticプロパティでも可
static defaultProps = {
name: 'defaultName'
};