Edited at

ここからはじめるReactの基礎の基礎

More than 1 year has passed since last update.


はじめに

この記事はReactの実装をしたことがない人、JSというとjQueryくらいしかやったことがない人でも理解出来るような内容です。

Reactをはじめるというとチュートリアルからはじめるのが基本かと思いますが、チュートリアルよりミニマムにReactってどんなの?というものを実際に実装して感じようというのが目的です。

ただし、npmはインストール済みが前提なのでnpmの準備は各自お願いします。

この記事ではReactの概念よりも実装を重要視します。なぜReactが良いのか等は他記事に譲らせて頂きます。

Reactを使うとなぜjQueryが要らなくなるのか

なぜ仮想DOMという概念が俺達の魂を震えさせるのか

簡単に説明すると、ReactはVirtual DOM (仮想DOM)という概念がキーポイントになり、それによって設計面、速度面に利点があります。特徴としてコンポーネントbaseのUIライブラリであることが挙げられて、実装する際にはこのコンポーネントについて理解することが重要です。

また、Fluxというアーキテクチャもありますが、今回はReactの基礎の基礎なので触れません。参考までにReduxがおすすめでチュートリアルも参考になりました。

Redux Tutorial

記法はES6を採用しています。


デモ

今回作成するのは以下のようなデモです。

react3.gif


環境構築

まず環境構築を行います。gaearon/react-hot-boilerplate を使ってセットアップします。

$ git clone git@github.com:gaearon/react-hot-boilerplate.git

$ cd react-hot-boilerplate
$ npm install
$ npm start

ここでhttp://localhost:3000/にアクセスして 「Hello, world.」が表示されれば成功です。

これで準備は完了です。

さて、とりあえず表示は出来ました。ここからはその仕組みについて少し解説します。

この箇所ははじめはあまり理解できなくても問題はないのでよく分からなければさらっと読み飛ばしても構いません。


webpack

このレポジトリではwebpackというビルドツールが使われています。

参考までにですが、以下の記事が分かりやすいと思います。

webpack で始めるイマドキのフロントエンド開発

すごくざっくりというと、書いたJSファイル(Reactのコード)をひとつのファイルにいい感じにまとめて出力してくれる やつです。

設定ファイルは webpack.config.js に書かれています。


仕組み

注目すべきファイルは以下の4つです。


  • webpack.config.js

  • index.html

  • src/index.js

  • src/App.js

まず、src/index.jssrc/App.jsを読み込んでいます。

読み込みは import App from './App';の部分です。


src/index.js

import React from 'react';

import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));


使うときはwebpack.config.jsの設定によって そのsrc/index.jsstatic/bundle.js にコンパイルされます。

そのため表示されるファイルの index.html で、 static/bundle.jsを読み込んでいます。


index.html

<!doctype html>

<html>
<head>
<title>Sample App</title>
</head>
<body>
<div id='root'>
</div>
<script src="/static/bundle.js"></script>
</body>
</html>

さて、ここで再度 src/index.jsを見てみます。


src/index.js

import React from 'react';

import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));


ReactDOM.render(<App />, document.getElementById('root')); の記述があると思いますが、これはid='root'の要素の中に<App />という要素を入れ込むという意味です。ここで<App />src/App.jsのことを指しています。

つまり、src/App.js に書いた記述がブラウザ上のページ(index.html)に反映される状態になっています。

ここでsrc/App.jsを見てみると確かに Hello, world.の記述がありますね。


src/App.js

import React, { Component } from 'react';

export default class App extends Component {
render() {
return (
<h1>Hello, world.</h1>
);
}
}


以降の実装では、このsrc/App.jsにコードを書いていくことで実装を行っていきます。


実装

実装のときにポイントとなるのは


  • Component

  • state

  • props

の3点です。

以下の図を見ながら考えてみて下さい。

Twitterの画面を例にしてみます。ツイートのタイムラインがあります。それを親コンポーネントとすると、ひとつひとつのツイートのボックスが子コンポーネントにあたります。そのようにひとつひとつをコンポーネントに見立てていく感覚が大切です。

また、コンポーネントごとの変数を管理をstateが、コンポーネント間の変数の受け渡しをpropsが担います。

react-component.png

それでは実際に実装していきます。


state

最初はコンポーネントはひとつしかありません。それはHello Worldを出力するコンポーネントです。

厳密ではないですが、ひとつひとつのクラスがコンポーネントになっているイメージです。

まず以下のように編集してみましょう。


src/App.js

import React, { Component } from 'react';

export default class App extends Component {
constructor(props) {
super(props);
this.state = {
name: 'James'
}
}

render() {
const name = this.state.name;

return (
<h1>Hello, {name}.</h1>
);
}
}


コンポーネント内に変数を用意します。コンポーネント内部の変数はstateでしたね。まずは初期値を用意しなければなりません。

そのためにconstructorを使います。constructorは初期化のための特殊なメソッドですので覚えてしまいましょう。super(props)の記述はconstructorをオーバーライドするので書きますが、はじめは決まりごととして覚えて構いません。そして以下のような記述によってstateを設定することが出来ます。

  constructor(props) {

super(props);
this.state = {
name: 'James'
}
}

実際にこれを表示しましょう。this.state.nameのような記述でstateにアクセス出来ます。また{}で囲むことで変数を表示することが出来ます。

  render() {

const name = this.state.name;

return (
<h1>Hello, {name}.</h1>
);

スクリーンショット 2016-10-02 11.30.06.png

これで反映されました。


onChange

ここでinputの入力欄をつくります。


src/App.js

import React, { Component } from 'react';

export default class App extends Component {
constructor(props) {
super(props);
this.state = {
name: 'James'
}
}

render() {
const name = this.state.name;

return (
<div>
<h1>Hello, {name}.</h1>
<input
type="text"
value={name}
onChange={ e => {
this.setState({
name: e.target.value
})
}}
/>
</div>
);
}
}


以下のようにinputの入力欄を作成出来ます。ちなみに一見htmlですがJSXという記法になります。ほとんどhtmlライクに書けます。

さて注目はonChangeですがこれはイベントハンドラです。inputの変更を検知して処理が行われます。ここでは文字を変更させたら{}内の処理が実行します。onClick等他のものもあるので調べてみると良いかと思います。

また、this.setStateによってstateの値を変化させています。注意ですが、this.state.name = 'hoge'のように変更してはいけません。this.setStateを使うことによって画面に変更が反映されます。

ちなみにe.target.valueeでeventを受けてinputに入力したvalue値を取っています。

また => これはES6のアロー関数を採用しているものなので気になる方は調べて見て下さい。

<input

type="text"
value={name}
onChange={ e => {
this.setState({
name: e.target.value
})
}}
/>

もう一点注意ですが、<h1><input><div>で囲っています。これはreturnの中のDOM要素はひとつにしないとエラーになるためです。

以下のように反映されているはずです。

react2.gif


props

機能自体はほぼ出来ましたが、名前表示の部分だけを子のコンポーネントに切り出してみます。

また、stateの初期値を空にしておきます。


src/App.js

import React, { Component } from 'react';

class Name extends Component {
render () {
const name = this.props.name;

return (
<span style={{color: 'red'}}>{name}</span>
);
}
}

export default class App extends Component {
constructor(props) {
super(props);
this.state = {
name: ''
}
}

render() {
const name = this.state.name;

return (
<div>
<h1>Hello, <Name name={name} />.</h1>
<input
type="text"
value={name}
onChange={ e => {
this.setState({
name: e.target.value
})
}}
/>
</div>
);
}
}


子のコンポーネントを以下のように作成しました。ポイントはpropsです。親で指定したprops(指定の仕方はこの後で)をstateと同じ要領で呼び出します。これでreturnの中身を親コンポーネントで表示出来ます。

class Name extends Component {

render () {
const name = this.props.name;

return (
<span style={{color: 'red'}}>{name}</span>
);
}
}

さて親コンポーネントで子コンポーネントの呼出ですが以下のような<Name />で呼び出せます。<Name name={name} />のようにプロパティを指定するとpropsとして子コンポーネントに値を引き渡せます。

<h1>Hello, <Name name={name} />.</h1>

以上で以下のように反映されます。

react3.gif

これで完成です!


終わりに

これだけ分かればReactの基礎の基礎は分かったことになると思います。以降チュートリアルをやるなどやってみましょう。

React チュートリアル

今回採用したES6でのチュートリアルも作成されていました。

ES6版React.jsチュートリアル

また、僕のReact勉強のログとして以下のレポジトリにまとめてあります。(そのため、チュートリアルほぼそのままのやつもあったりです。今度アップデートさせたいと思っています。)

ローカルで起動させると教科書的に使えるかと思うので参考になれば幸いです。

今回の記事の内容の機能もこれの一番最初のデモです。

kuboshizuma/react-practice