システム開発現場の道具箱

株式会社モノクレアが運営するIT技術系のブログです。システム開発の現場で役に立つ情報を掲載しています。

React入門ハンズオン

create-react-appを使ったReactアプリケーションの作成方法を紹介します。アプリケーションを作成するのに必要な機能を扱っています。実際にアプリケーションを作って動かしながら試してみてください。

  • 準備
    • Node.jsのインストール
    • create-react-appのインストール
    • プロジェクトの作成、開発環境の確認
  • 本編
    • コンポーネントの作成
    • 入力フォームの作成
    • REST APIサーバーとREST API呼び出しの作成
    • 画面遷移の作成
    • マテリアルデザインの適用
    • 配布資材の生成

この記事の内容は2017/7/23のSI-Toolkitユーザーグループ React.js入門ハンズオン勉強会で使用したものです。

準備

Node.jsのインストール

https://nodejs.org/ja/からインストーラーをダウンロードして実行します。

create-react-appのインストール

以下のコマンドを実行し、create-react-appをインストールします。

npm install -g create-react-app

プロジェクトの作成、開発環境の確認

以下のコマンドを実行し、Reactアプリケーションのプロジェクトを作成して実行します。 ブラウザが起動し、Reactアプリケーションが表示されます。

create-react-app react-app-1
cd react-app-1
npm start

srcディレクトリのファイル:App.jsを以下の様に編集します。 ファイルを保存すると、変更は即座にブラウザで表示中のアプリケーションに反映されます。 編集内容にエラーがある場合はnpm startを実行しているウィンドウに表示されます。

import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div>
        Empty!
      </div>
    );
  }
}

export default App;

本編

コンポーネントの作成

srcディレクトリにファイル:NumberCmp.jsを作成し、以下の様に実装します。

import React, { Component } from 'react';

class NumberCmp extends Component {

  render() {
    return (
      <div>number : {this.props.number}</div>
    )
  }
}

export default NumberCmp;

src/App.jsでNumberCmpを使用する様に実装します。

import React, { Component } from 'react';
import NumberCmp from './NumberCmp';

class App extends Component {

  render() {
    return (
        <div>
          <NumberCmp number="1"/>
        </div>
    )
  }
}

export default App;

ブラウザに「number : 1」が表示されることを確認します。

参考

入力フォームの作成

srcディレクトリにファイル:FormCmp.jsを作成し、以下の様に実装します。

import React, { Component } from 'react';

class FormCmp extends Component {

  constructor(props) {
    super(props);

    this.state = {in : ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);

  }

  handleChange(event) {
    this.setState({in : event.target.value});
  }

  handleSubmit(event) {
    event.preventDefault();

    alert(this.state.in);
  }

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input type="text" name="in" value={this.state.in} onChange={this.handleChange}/>
          <input type="submit"/>
        </form>
      </div>
    )
  }
}

export default FormCmp;

NumberCmpと同様にFormCmpをAppで使用する様に実装します。

ブラウザにテキストボックスと送信ボタンが表示されること、また送信ボタンをクリックするとテキストボックスに入力した文字列がアラートで表示されることを確認します。

参考

REST APIサーバーとREST API呼び出しの作成

REST APIサーバーの作成

以下のコマンドを実行し、自動再起動機能を持った開発用Nodeサーバーをインストールします。

npm install -g node-dev

REST APIサーバー用のプロジェクトをreact-app-1とは別のディレクトリに作成します。

mkdir rest-api-server
cd rest-api-server
npm init
npm install express --save

rest-api-serverディレクトリにファイル;app.jsを作成し、以下の様に実装します。

var express = require('express');
var app = express();

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/', function (req, res) {
  res.json({key:'value'});
});

var server = app.listen(3010, function () {
  console.log('app listening on port ' + server.address().port);
});

以下のコマンドを実行し、REST APIサーバーを起動します。

node-dev app.js

http://localhost:3010/ をブラウザで開くと「{“key”:“value”}」が表示されることを確認します。

REST API呼び出し

srcディレクトリにファイル:FetchCmp.jsを作成し、次の通り実装します。

import React, { Component } from 'react';

class FetchCmp extends Component {

  constructor(props) {
    super(props);

    this.state = {key : ''};
  }

  componentDidMount() {
    fetch('http://localhost:3010/')
    .then(res => res.json())
    .then(res => this.setState(res));
  }

  render() {
    return (
      <div>Fetch {JSON.stringify(this.state)}</div>
    )
  }
}

export default FetchCmp;

ブラウザに「Fetch {“key”:“value”}」が表示されることを確認します。

参考

画面遷移の作成

react-routerを使用して画面遷移を実装します。

次のコマンドを実行し、必要なライブラリをインストールします。

npm install --save react-router react-router-dom

src/index.jsを次の様に編集します。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter as Router } from 'react-router-dom' // add

// add Router element
ReactDOM.render(
    <Router>
        <App />
    </Router>,
document.getElementById('root'));
registerServiceWorker();

src/App.jsを次の様に編集します。

import React, { Component } from 'react';

import { Route, Link, withRouter } from 'react-router-dom'

import NumberCmp from './NumberCmp';
import FormCmp from './FormCmp';
import FetchCmp from './FetchCmp';


class App extends Component {

  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.history.push('/fetch')
  }

  render() {
    return (
      <div>
        <ol>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/number">Number</Link></li>
          <li><Link to="/form">Form</Link></li>
          <li><button onClick={this.handleClick}>Fetch</button></li>
        </ol>
        <Route path="/number" component={NumberCmp} number={2} />
        <Route path="/form" component={FormCmp} />
        <Route path="/fetch" component={FetchCmp} />
      </div>
    )
  }
}

export default withRouter(App);

参考

マテリアルデザインの適用

マテリアルデザインを適用するためのライブラリはいくつもありますが、ここではMaterial UIを使用します。 以下のコマンドを実行しMaterial UIとそれが依存するライブラリをインストールします。

npm install react-tap-event-plugin material-ui

src/index.jsを以下の様に変更します。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter as Router } from 'react-router-dom' 
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';   // add
import injectTapEventPlugin from 'react-tap-event-plugin';   // add

injectTapEventPlugin();  // add


// add MuiThemeProvider element
ReactDOM.render(
    <Router>
       <MuiThemeProvider>
        <App />
       </MuiThemeProvider>
    </Router>,
document.getElementById('root'));
registerServiceWorker();

src/FormCmp.jsを以下の様に変更します。

import React, { Component } from 'react';
import RaisedButton from 'material-ui/RaisedButton';   // add
import TextField from 'material-ui/TextField';   // add

class FormCmp extends Component {

 :

  render() {
    // <input type="text"  =>  <TextField
    // <input type="submit"  =>  <RaisedButton 
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <TextField hintText="hint" floatingLabelText="floatingLabel" name="in" value={this.state.in} onChange={this.handleChange}/>
          <RaisedButton type="submit" label="送信" primary={true}/>
        </form>
      </div>
    )
  }

ブラウザでテキストボックスと送信ボタンにマテリアルデザインが適用されていることを確認します。

参考

配布資材の生成

以下のコマンドを実行し、Reactアプリケーションの配布可能な資材を生成します。

npm run build

buildディレクトリ以下に配布可能な資材が生成されます。