Reactを使って開発することのメリットの一つにコンポーネントでフロント画面のパーツを作って再利用できることにあります。今回はReactでコンポーネントを使う方法を説明します。本記事はコンポーネントについて聞いたことあるはあるけど使ったことない人や、Vueなどでコンポーネント使ったことあるけどReactでは使ったことない人を対象にしています。
本記事の前提
本記事はcreaate react app
コマンドで作成していること前提にしています。Webpackなどのモジュールバンドラを導入している前提です。また、以下の知識を前提としています。
- Node.js 8.1以上とnpm 5.6以上がインストールされている
create react app
でのプロジェクトの立ち上げが(なんとなく)わかる- JavaSceriptのクラスの使い方について(なんとなく)わかる
- import文、export文が(なんとなく)わかる
JavaScriptのクラスについては「クラスの書き方・使い方について解説」を参考にするといいと思います。
作成する画面
今回は以下のような画面を実装します。
ボタンを押すとカウントが増えていくだけの画面です。こんなシンプルな画面ですが、3つのコンポーネントで丁寧に作ります。作成するコンポーネントは以下の表にまとまっています。
コンポーネント名 | 役割 |
TopPage | ページ全体の要素 |
CountDisplay | カウントを表示する部分 |
AddButton | カウントアップをするボタン |
作成手順
作成手順は以下のようになります。
- create react appでプロジェクトの立ち上げ
- publicフォルダ、srcフォルダの整理
- index.html, index.jsの編集
- 各コンポーネントの作成
- stateとpropの指定
- イベントハンドリングの指定
今回使用したコードはcode-databaseのgithubリポジトリにも公開されていますので、手元で確認したい方は参考にしてみてください。
実際に作ってみる
先ほどの手順に則って機能を作っていきましょう!
create react appでプロジェクトの立ち上げ
まずはプロジェクトを立ち上げます。以下のコマンドでプロジェクトフォルダを作成しましょう。
タイトル:ターミナル
$ npx create-react-app sample-app
*create-react-app
コマンドがglobalインストールされている方はエラーが起きる可能性があります。npm uninstall -g create-react-app
でアンインストールしましょう。アンストールができない場合もあります。その場合はwhich craete-react-app
で表示されるファイルを直接削除してみましょう。
publicフォルダ、srcフォルダの整理
プロジェクトフォルダができたらデフォルトで入っているpublicフォルダとsrcフォルダ内のファイルで不要なものを削除します。publicフォルダ内のindex.html、srcフォルダ内のindex.js以外は削除してしまいましょう。
続いてsrcフォルダ内にpagesフォルダとcomponentsフォルダを作成します。pagesフォルダにはページのコンポーネントを、componentsフォルダにはページ内の部品となるコンポーネントを作成することにします(フォルダの分け方に特に指定はありません)。
さらに、pagesフォルダとcomponentsフォルダにコンポーネントを記述するファイル(TopPage.js, CountDisplay.js, AddButton.js)を作成します。ここまでの整理でディレクトリ構造は次のようになっています。
タイトル:フォルダ階層
sample-app/ ├ node_modules/ ├ public/ │ └ index.html ├ src/ │ ├ pages/ │ │ └ TopPage.js │ ├ components/ │ │ ├ CountDisplay.js │ │ └ AddButton.js │ └ index.js
index.html, index.jsの編集
続いて先ほど残したindex.htmlとindex.jsファイルを編集します。まずはindex.htmlを編集しましょう。
タイトル:index.html
<!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>sample-app</title> </head> <body> <div id='root'></div> </body> </html>
div#rootのみをbody内に記述するだけで大丈夫です。続いてindex.jsを編集します。
タイトル:index.js
import React from 'react' import ReactDOM from 'react-dom'; import TopPage from './pages/TopPage.js' ReactDOM.render( React.createElement(TopPage), document.getElementById('root') );
index.jsにはTopPageを読み込み、これを先ほどhtmlファイルで指定したdiv#rootに描画する処理を記述します。
ReactDOM.renderというメソッドを用いて実際のDOMに変更を適用します。renderメソッドの第一引数には描画する要素を指定しますが、今回はReact.createElementメソッドで生成された要素を指定します。createElementメソッドは引数にコンポーネントなどを指定して要素を生成するメソッドです。renderメソッドの第二引数にはDOMの描画を行うhtml要素を指定します。
各コンポーネントの作成
本記事のメインテーマになっているコンポーネントを作成していきましょう。まずはTopPageを作成します。
タイトル:TopPage.js
import React from 'react' import CountDisplay from '../components/CountDisplay' import AddButton from '../components/AddButton' export default class TopPage extends React.Component{ render() { return ( <div> <CountDisplay/> <AddButton/> </div> ) } }
CountDisplayとAddButtonをそれぞれインポートしてrenderメソッドで表示をしています。CountDisplayとAddButtonについてもrenderメソッドでhtml要素をJSXで記述します。
タイトル:CountDisplay.js
import React from 'react' export default class CountDisplay extends React.Component { render() { return ( <div>カウント:</div> ) } }
タイトル:AddButton.js
import React from 'react' export default class AddButton extends React.Component{ render() { return ( <button>add</button> ) } }
stateとpropの指定
TopPageにstateを持たせてカウントを状態として保存できるようにします。さらにこのカウントをCountDisplayに渡して表示ができるようにします。まずはTopPageにstateを持たせるようにしましょう。
タイトル:TopPage.js
export default class TopPage extends React.Component{ //追記 constructor(props) { super(props) this.state = { count :0 } } render() { return ( <div> <CountDisplay count={this.state.count}/> //追記 <AddButton/> </div> ) } }
constructorメソッドでstateを定義して、countというstateを作成して初期値を0に指定します。
さらにCountDisplayにデータを渡すために<CountDisplay count={this.state.count}/>
を記述します。次にCountDsplay渡したcountをpropsとして受け取ります。
タイトル:CountDisplay.js
render() { return ( <div>カウント:{ this.props.count }</div> //追記 ) }
上記のようにpropsで受け取ったデータを使用することができます。
イベントハンドリングの指定
最後にAddButtonでボタンをクリックするとcountが増えるようにするため、AddButtonのクリックイベントをTopPageでハンドリングできるようにしましょう。
タイトル:TopPage.js
export default class TopPage extends React.Component{ constructor(props) { super(props) this.state = { count :0 } this.addCount = this.addCount.bind(this) //追記 } //追記 addCount() { this.setState((state) => { return { count : state.count + 1 } }) } render() { return ( <div> <CountDisplay count={this.state.count}/> <AddButton onAddCount={this.addCount}/> //追記 </div> ) } }
まずはaddCountメソッドを定義してsetStateメソッドでcountを一つ増やすためのハンドラを用意します。この際にthis.addCount = this.addCount.bind(this)
をconstructorメソッド内に記述してaddCountメソッドでのthisでTopPageを参照できるようにします。この記述がないとaddCountメソッド内でのthisがundefined
になってしまします。作成したaddCountメソッドは<AddButton onAddCount={this.addCount}/>
でpropsと同じようにしてAddButtonに渡します。
タイトル:AddButton.js
export default class AddButton extends React.Component{ //追記 constructor(props) { super(props) this.handleClick = this.handleClick.bind(this); } //追記 handleClick() { this.props.onAddCount() } render() { return ( <button onClick={this.handleClick}>add</button> //追記 ) } }
続いてAddButtonで先ほどonAddCountとして渡されたメソッドをAddButtonで定義したhandleClickメソッドを介して使用できるようにします。こちらでもconstructorメソッド内でthisをbindするのを忘れないようにしましょう。
お疲れ様でした!これで全ての機能を実装できました。
タイトル:ターミナル
$ npm run start
上のコマンドでローカルホストを立ち上げて正常に動くか確認してみましょう。
上のように機能すれば問題ないです。
この記事のまとめ
今回はカウントアップアプリを題材にReactのコンポーネントを説明しました。最後の記事の要点をまとめておきましょう。
- コンポーネントを使うことでページの要素を再利用しながら作成できる
- stateでコンポーネントの状態を扱うことができる
- propsでコンポーネント間の値渡しを行うことができる
- propsでメソッドも渡すことができる
皆さんもReactでコンポーネントを活用しましょう!