create-reacte-appとMaterial-UIで簡単にいけてそうなReactアプリケーションを作る
今日は今流行りに流行ってるReactについての記事を書こうと思います。 かなり初歩的な内容ですが、初心者の方にはうってつけかと思います。
- 目標
- create-react-appを使おう
- インストール
- 実行してみる
- ちょっと変更してみる前にApp.jsを確認
- App.jsをいじる
- ちょっといい感じのUIコンポーネントつけてみる
- ちょっと解説
- まとめ
目標
ReactでHelloWorldよりも少し凝ったWebサイトを作れるようになる
create-react-appを使おう
ReactでWebアプリケーションを作成するためのとっかかりがめんどくさいので簡単にBoilerPlateを作成する必殺技があります。 それが今回ご紹介するcreate-react-appです。
インストール
今回はyarnを使って行きたいと思いますが、別にnpmでも構いません。適宜読み替えてください。 まずはnodeとyarnのバージョンを確認します。
$ node -v v8.14.0 $ yarn -v 1.12.3
続いて今回使うcreate-react-appをglobalにインストールします。
$ yarn add -global create-react-app
今回作成するアプリケーションはreact-exampleとします。 自分の作業したいディレクトリで以下のコマンドを実行します。
$ create-react-app react-example
すると
$ create-react-app react-example Creating a new React app in /Users/regpon/test/react-example. Installing packages. This might take a couple of minutes. Installing react, react-dom, and react-scripts... yarn add v1.12.3 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 📃 Building fresh packages... success Saved lockfile. success Saved 22 new dependencies. info Direct dependencies ├─ react-dom@16.7.0 ├─ react-scripts@2.1.3 └─ react@16.7.0 info All dependencies ├─ @babel/runtime@7.1.5 ├─ autoprefixer@9.4.4 ├─ babel-plugin-transform-react-remove-prop-types@0.4.20 ├─ babel-preset-react-app@7.0.0 ├─ cssdb@4.3.0 ├─ detect-node@2.0.4 ├─ eslint-config-react-app@3.0.6 ├─ handle-thing@2.0.0 ├─ postcss-color-gray@5.0.0 ├─ postcss-custom-media@7.0.7 ├─ postcss-custom-properties@8.0.9 ├─ postcss-double-position-gradients@1.0.0 ├─ postcss-preset-env@6.3.1 ├─ react-app-polyfill@0.2.0 ├─ react-dev-utils@7.0.1 ├─ react-dom@16.7.0 ├─ react-error-overlay@5.1.2 ├─ react-scripts@2.1.3 ├─ react@16.7.0 ├─ spdy-transport@3.0.0 ├─ spdy@4.0.0 └─ webpack-dev-server@3.1.14 ✨ Done in 16.93s. Initialized a git repository. Success! Created react-example at /Users/regpon/test/react-example Inside that directory, you can run several commands: yarn start Starts the development server. yarn build Bundles the app into static files for production. yarn test Starts the test runner. yarn eject Removes this tool and copies build dependencies, configuration files and scripts into the app directory. If you do this, you can’t go back! We suggest that you begin by typing: cd react-example yarn start Happy hacking!
こんな具合にインストールが始まります。
作成されたreact-example
ディレクトリをVisualStudioCodeで開いてみると、
こんな感じでファイルが作成されていると思います。 これでインストールは完了です。
実行してみる
react-example
ディレクトリ に移動して以下のコマンドを実行します。
$ cd react-example $ yarn start
上記のコマンドを実行すると、自動で以下が表示されたブラウザが立ち上がります。
また、コンソールには以下が表示されていると思います。
Compiled successfully! You can now view react-example in the browser. Local: http://localhost:3000/ On Your Network: http://192.168.11.63:3000/ Note that the development build is not optimized. To create a production build, use yarn build.
これでReactによるWebアプリケーションの起動の確認まで完了です。
ちょっと変更してみる前にApp.jsを確認
ブラウザの指示通りに、src/App.js
を少しいじってみましょう。
デフォルトだと、
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } } export default App;
こんな感じです。ざっくり説明すると、このApp.js
にはReact
のComponent
クラスを拡張したApp
クラスというクラスがあり、そのクラスにはrender()
という関数が定義されています。
Component
とは一言で言うと部品のことで、React
はフロントサイドのフレームワークなのでここで言う部品とは、DOM上に表示される意味を持った塊のようなものです。
例えば、このWikiであれば、上部のメニューバーや編集画面の編集フィールド、プレビューフィールドなどが部品になっています。
また、その部品をさらに細かく管理することもできますが、細かすぎると意味不明になるので、よく言われるのは3回程度他のページでも使い回される部品はComponent
化するといいそうです。
そして、このrender()
関数はComponent
が呼び出されて、サーバーサイドでレンダリングする際に呼ばれます。
React
はNode.jsのフレームワークなのでサーバーサイドでレンダリングし、クライアントにはHTMLを返します。つまりJavascriptからHTMLを生成する工程をサーバーサイドで行うと言うことです。
ここではsrc/index.js
がApp.js
をコンポーネントとして呼び出しているので、そいつが実行されることでこれらの処理が作動します。index.js
については説明は端折りますが、最初に呼ばれるjsファイルなんだな。こいつに他のjsファイルを実行させるんだなと思っといてください。
コンポーネントをサーバーサイドレンダリングする際に実行されるのがrender()
関数で、みてみるとすぐにreturn()
をして、なにやらHTMLを返しています。
これは厳密言うとHTMLではなくJSX
と呼ばれる構文のなのですが、Javascriptとして扱うHTML
のようなものです。
JSX
は必ず一つのタグでなければならないと言う制約があります。一つといっても階層構造が一つであればいいので、上記のように子のタグを持つ分には問題ないです。
class App extends Component { render() { return ( <div className="App"> <p>aaa</p> </div> <p>bbb</p> ); } }
上述のように<div></div>
と同じ階層に<p></p>
がいるような状態がダメということですね。
シンタックスをみても変な感じになってますよね。ちゃんとJSX
として認識されていない証拠です。
App.jsをいじる
まぁここまで説明したらあとは好きにいじってもらえればと思います。
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> SIerからWeb系に転職したやつの日記 </p> <p> SIerやめてよかった </p> </header> </div> ); } } export default App;
くだらないですがちょっと上記のように修正しました。 この状態で保存するだけで即反映されます。
ちょっといい感じのUIコンポーネントつけてみる
ここではMaterial-UIを使っていい感じの見た目のコンポーネントを付け加えてみようと思います。 Material-UIってのはbootstrapみたいな感じでいい感じの見た目にしてくれるやつで、Googleが提唱しているマテリアルデザインをReactで実現できるようにしたものです。
こいつをまずインストールします。
$ yarn add material-ui
続いて、Material-UIを使ってメニューバーをつけてみましょう。
そのためにまずsrc
ディレクトリにコンポーネント用のディレクトリを作り、そこに作成して行きたいと思います。
作成するファイル:src/component/MenuBar.js
※コマンドはだるいのでVisualStudioCodeで作業しましょう。
import React, { Component } from 'react'; import AppBar from 'material-ui/AppBar'; class MenuBar extends Component { render() { return ( <AppBar title="React Example" iconClassNameRight="muidocs-icon-navigation-expand-more" /> ) }; } export default MenuBar;
次に、このメニューバーを読み込みために、index.js
に呼び出させます。
index.js
はデフォルトだとこんな感じだと思います。
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App />, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
これを以下のように変更してください
import React from 'react'; import ReactDOM from 'react-dom'; import MenuBar from './component/MenuBar'; import App from './App'; import * as serviceWorker from './serviceWorker'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; ReactDOM.render( <React.Fragment> <MuiThemeProvider> <MenuBar /> </MuiThemeProvider> <App /> </React.Fragment>, document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
これで保存して実行すればメニューバーが上部に出ると思います。
左上のハンバーガーメニューをクリックしても今はなにも出ませんが、メニューをつけるようにすることも可能です。
ちょっと解説
コンポーネント編
まずMenuBar
コンポーネントから簡単に説明します。
まぁめちゃくちゃ単純です
import React, { Component } from 'react'; import AppBar from 'material-ui/AppBar'; class MenuBar extends Component { render() { return ( <AppBar title="React Example" iconClassNameRight="muidocs-icon-navigation-expand-more" /> ) }; } export default MenuBar;
まず、先ほどyarn add
したmaterial-ui
のAppBar
というものをimport
しています。これはMaterial-UIにおける画面上部に設置するメニューバーはこれ使っとけばええ感じにするで。ってやつで、オプションでタイトルとハンバーガーメニューの表示を指定してます。
これをApp.js
同様、Component
クラスを拡張させてrender()
関数に記載しました。
index.js編
次にindex.js
ですが、
import React from 'react'; import ReactDOM from 'react-dom'; import MenuBar from './component/MenuBar'; import App from './App'; import * as serviceWorker from './serviceWorker'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; ReactDOM.render( <React.Fragment> <MuiThemeProvider> <MenuBar /> </MuiThemeProvider> <App /> </React.Fragment>, document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
基本的には追加をしただけですね。
import MenuBar from './component/MenuBar';
は作成したコンポーネントをindex.js
で使えるようにimport
しているだけ。
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
はMaterial-UIを動かすためのコンポーネントで、これもまたimport
しています。
続いてReactDOM.render()
ですが、結構大きく変わったように見えますが、改行して、<App />
以外を追加しただけです。
まず、JSXのタグは一つの原則に基づいて、複数コンポーネントを表示するために親のタグを<App>
から変える必要があったので、<React.Fragment></React.Fragment>
でくくりました。これは慣例のようなものですね。<div></dix>
でくくって一つのタグとしてもいいのですが、<div>
を使うとブラウザ側にも<div>
が返ってしまい、無駄なDOMツリーができてしまいます。JSXの制約のために一つにまとめたいだけの時は、<React.Fragment>
で括ることで、ブラウザ側には無駄な階層が表示されません。
試しにやってみると、
ReactDOM.render( <div> <MuiThemeProvider> <MenuBar /> </MuiThemeProvider> <App /> </div>, document.getElementById('root') );
の場合は、
ReactDOM.render( <React.Fragment> <MuiThemeProvider> <MenuBar /> </MuiThemeProvider> <App /> </React.Fragment>, document.getElementById('root') );
の場合は、
のように、<div id="root">/div>
の一個下の階層にあった余分な<div></div>
が消えているのがわかります。
細かいところではありますが、不必要にタグを増やすとレンダリングコストや表示コストの増加に繋がりますし、何より見にくくなるので覚えておきましょう。
あとは新たに作成したMenuBar
コンポーネントを呼び出すために、MuiThemeProvider
コンポーネントを呼び出し、MenuBar
コンポーネントの親階層にしています。Material-UIで作成したコンポーネントは皆、MuiThemeProvider
コンポーネントの子階層として呼び出さないと動かないので、このように書きます。
まとめ
いかがだったでしょうか。create-react-appとMaterial-UIを使えばあっちゅーまにいい感じの見た目のWebアプリが作れちゃいます。いろいろ試しながらやってみてはいかがでしょうか。
Material-UIのリファレンスに使い方はまとまっていて、サンプルも充実しているのでよかったらコピペしてコンポーネント作ってみてはどうですか? Material-UIのCardとかいけてるSNSのUIっぽくて結構好き。
Card使ってアフロのSNSっぽいページ作ってみたのがこれ。ほぼコピペ。
これであなたもReactエンジニアです。