こんにちは、mabuiです。
下記コードを使用して、reactのコア機能であるレンダリング処理の説明をします。
なお動作環境は1クリックで用意できるオンラインエディタのcodesandboxを使用しています。
CodeSandbox: Online Code Editor Tailored for Web Application Development
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import React from "react"; import ReactDOM from "react-dom"; // stateを更新するためのデータ const COINS = [ { name: "Bitcoin", symbol: "BTC", rank: "1" }, { name: "Ethereum", symbol: "ETH", rank: "2" }, { name: "Ripple", symbol: "XRP", rank: "3" } ]; // Reactコンポーネント作成 class ExplainRender extends React.Component { renderCoins() { var list = []; for (let key in COINS) { let coin = COINS[key]; // データをJSXで変換して配列に詰める。 list.push( <li> rank: {coin["rank"]}, name: {coin["name"]}, symbol: {coin["symbol"]} </li> ); } // setTimeoutで待たないとsetStateとrenderが同時に走るため、2回目のrenderが走らない。 setTimeout(() => { // stateが更新されたら、render()が自動的に実行される。 this.setState({ list: list }); }, 100); } constructor() { console.log("処理順1"); super(); // コンストラクタでrenderCoins実行。 this.renderCoins(); this.state = { list: [] }; } render() { console.log("処理順2"); return <ul>{this.state.list}</ul>; } } ReactDOM.render( // Reactコンポーネントをレンダリング <ExplainRender />, document.getElementById("root") ); |
二種類のrenderメソッド
Reactには二種類のrenderメソッドがあります。
ReactDOM.render()はReactエレメントをドキュメント(生成されるhtml等の文書)にレンダリングする役割です。
Reactコンポーネントのクラスで呼び出されているrenderでは、JSXなどで定義されたReactエレメントを返す処理を行っています。
両メソッドとも、複数のコンポーネントを返すことは出来ません。
1 2 3 4 5 6 7 |
render() { return ( <div>hoge</div> <div>fuga</div> ) } |
下記のようにひとまとめのブロックにしましょう。
1 2 3 4 5 6 7 8 9 |
render() { return ( <div> <div>hoge</div> <div>fuga</div> </div> ) } |
レンダリングが目的のメソッドなので、その他の処理を持たせないようにしましょう。
Reactでレンダリングプロセスを管理する際は、UNIX哲学を念頭に置くべきです。特に「Smal l is beautiful」(小さいものは美しい)、「Make each program do one thing well」(各プログラムが1つのことをうまくやるようにせよ)、「Choose portabillity over efficiency」(効率よりも移植しやすさを選べ)などの設計思想は、持ち込みやすく、扱いやすいReactコンポーネントを生み出す鍵となるでしょう。
石橋 啓太[著] React開発現場の教科書 p46
Reactコンポーネントとは
React.Componentクラスのrenderメソッドでreturnされるコンポーネントのことです。
JSXでタブ名のように記述できます。
1 2 3 4 5 6 |
ReactDOM.render( // Reactコンポーネントをレンダリング <ExplainRender />, document.getElementById("root") ); |
Reactコンポーネントのrenderメソッドの使い方
React.Componentの中でまっさきに呼び出されるのがrenderです。
Reactで画面を動かしたい場合は、setStateメソッドを使用して、stateを更新します。
そのたびにrenderが自動で呼び出されるため、stateの変更差分が画面に反映されます。
1 2 3 4 5 6 |
// setTimeoutで待たないとsetStateとrenderが同時に走るため、2回目のrenderが走らない。 setTimeout(() => { // stateが更新されたら、render()が自動的に実行される。 this.setState({ list: list }); }, 100); |
紹介したコードでは自動でrenderを呼び出すため、あえてコンストラクタで
stateを更新するメソッドを呼び出しています。
setTimeoutメソッドを使用しているのはsetStateとrenderの実行タイミングが被るためか、
setStateによる2回目のrenderの処理が走らなくなるためです。
上記はcodesandboxでのコードの実行画面です。
Consoleのログを見ると、コンストラクタ、renderの順に実行されて
再度renderが呼び出されていることが分かります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
constructor() { console.log("処理順1"); super(); // コンストラクタでrenderCoins実行。 this.renderCoins(); this.state = { list: [] }; } render() { console.log("処理順2"); return <ul>{this.state.list}</ul>; } |
renderはstateの更新のたびに呼ばれるため、ifによる分岐処理等はなるべく入れず、
冪等性を守った実装にしましょう。