LoginSignup
0

More than 5 years have passed since last update.

react.jsのお勉強

Last updated at Posted at 2018-06-13

ローカル開発環境構築

Reactはスクラッチからコードを書くのではなく、公開されているパッケージ類を組み合わせて開発環境を構築する。
パッケージはnpmコマンドでインストールする。
現在はcreate-react-appパッケージを入れれば必要なものは大方含まれている。

  • node.js インストール(npmコマンドを使うために)
    https://nodejs.org/ja/download/

  • create-react-appコマンドを利用可能にするためグローバルインストール

c:\>npm install -g create-react-app
  • プロジェクトの雛形を作成
c:\>create-react-app my-app
  • ↑で作成されたpackage.jsonに記載されているパッケージをまとめてインストール
    (node_modulesディレクトリにパッケージがインストールされる)
c:\>cd my-app
c:\my-app>npm install
  • ビルド実行+ローカルサーバー起動
c:\my-app>npm start

> my-app@0.1.0 start c:\my-app
> react-scripts start
Starting the development server...
Compiled successfully!

You can now view my-app in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://192.168.56.1:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

↑に出てきた http://localhost:3000/ にアクセスすると雛形ページが見れる。
index.htmlやApp.jsを変更すると反映されるのが確認できる。

ビルド

コンパイルしてアプリケーションに配備可能な状態にする。

c:\my-app>npm run buril

my-appディレクトリにbuildディレクトリが作成される。
この中にjsやらhtmlやらが生成されている。

アプリケーションに上記をアプリケーションに配置、もしくはしかるべき場所にbuildされるようにしておく。

ワークショップ

準備

Ctrl+Cで一旦ローカルサーバーを止め、

  • 雛形ファイルを削除
c:\my-app>del src\
c:\my-app>del public\
  • 空ファイルを作成
c:\my-app>del src\index.js        #空
c:\my-app>del public\index.html
index.html
<html>
<body>
Hello World!
<body>
</html>

npm start するとHello World!が確認できる。
この状態で index.js だったり index.html を編集していくことで開発できる。

Hello World!を表示する

index.html
<html>
<body>
    <div id="content">
        <!-- ここに生成されたDOMが書き出されます -->
    </div>
<body>
</html>
index.js
import App from './App';
App.js
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
    React.createElement(
        'p',
        { className: 'Hello' },
        'Hello World!'
    ),
    document.getElementById('content')
);

Hello World!でました!!!!!

入れ子のタグを作るときはこう。

ReactDOM.render(
    React.createElement(
        'p',
        { className: 'Hello' },
            React.createElement(
                'span',
                { className: 'Hello2' },
                'Hello World!'
            ),
    ),
    document.getElementById('content')
);

すごく見にくいので
JSX(jsの中にマークアップを書ける拡張構文)にしよう。

ReactDOM.render(
    // 指定したタグを書き出す
    // ※ 入れ子はできるけど、ルートの階層に複数タグを書くことはできない
    <p className='Hello'>
        <span className='Hello2'>Hello World!</span>
    </p>,
    document.getElementById('content')
);

みやすい!!!!!!ヽ(゜∀。)ノ

Component化

さきほどの Hello World! をコンポーネント化します。

App.js
import React from 'react';
import ReactDOM from 'react-dom';

import Hello from './Hello';

ReactDOM.render(
    <Hello />,
    document.getElementById('content')
);
Hello.js
import React, { Component } from 'react';

class Hello extends Component {
    render() { // 定義したコンポーネントをレンダリングするためのメソッド
        return(
            <p className='Hello'>
                <span className='Hello2'>Hello World!</span>
            </p>
        );
    }
}

export default Hello; // 定義したHelloをimport可能にする

値のやり取り

props:親から渡される情報(≒引数)
state:自Componentの状態

Hello World! の文字列を親から渡してみる

App.js
import React from 'react';
import ReactDOM from 'react-dom';

import Hello from './Hello';

ReactDOM.render(
    <Hello helloTitle='Hello World!' />,
    document.getElementById('content')
);
Hello.js
import React, { Component } from 'react';

class Hello extends Component {
    render() {
        return(
            <p className='Hello'>
                <span className='Hello2'>{this.props.helloTitle}</span>
            </p>
        );
    }
}

export default Hello;

Hello World! の文字列の状態を変更してみる

Hello.js
import React, { Component } from 'react';

class Hello extends Component {
    constructor(props) {
        super();
        // 親から受け取ったpropsをstateの初期値とする
        this.state = { helloTitle: props.helloTitle };
    }
    changeText() {
        // 自コンポーネントのイベントにより状態を変更
        this.setState({ helloTitle: 'Hello World!!!!!!' } );
    }
    render() {
        return(
            <p className='Hello' onClick={ () => this.changeText() }>
                <span className='Hello2'>{this.state.helloTitle}</span>
            </p>
        );
    }
}

export default Hello;

ここでは簡単に無名関数で onClick={ () => this.changeText() } と直接実行していますが、onClick={this.changeText} としてイベントを紐づけたほうがよいでしょう。
しかしその場合、イベント実行時にthisがバインドされない(changeText実行時にthis.setStateがundefinedになる)ので、super()後に下記を記述しておく必要があります。
this.changeText = this.changeText.bind(this);

繰り返し処理

App.js
import React from 'react';
import ReactDOM from 'react-dom';

import Hello from './Hello';

const hellos = ['Hello', 'こんにちは', 'Здравствуйте'];

ReactDOM.render(
    <Hello hellos={hellos} />,
    document.getElementById('content')
);
Hello.js
import React, { Component } from 'react';

class Hello extends Component {
    render() {
        // 配列データをmapメソッドで return JSX する
        const hellos = this.props.hellos.map((text) => {
            return <p>{text}</p>;
        });
        return(
            <p className='Hello'>
                {hellos}
            </p>
        );
    }
}

export default Hello;

これでもいい(定数に格納しないでjsx内に直接jsを書くことも出来る)

            <p className='Hello'>
                {this.props.hellos.map((text) => {
                    return <p>{text}</p>;
                })}
            </p>

コンポーネントのライフサイクル

Hello.js
import React, { Component } from 'react';

class Hello extends Component {
    constructor(props) {
        super();
        alert('①constructor');
        this.changeText = this.changeText.bind(this);
        // 親から受け取ったpropsをstateの初期値とする
        this.state = { helloTitle: props.helloTitle };
    }
    componentWillMount() {
        alert('②componentWillMount');
    }
    render() {
        alert('render');
        return(
            <p className='Hello' onClick={this.changeText}>
                <span className='Hello2'>{this.state.helloTitle}</span>
            </p>
        );
    }
    componentDidMount() {
        alert('③componentDidMount');
    }

    // --------------------------------

    // 廃止予定
    componentWillReceiveProps(nextProps) {
        alert('④componentWillReceiveProps');
    }

    shouldComponentUpdate(nextProps, nextState) {
        alert('⑤shouldComponentUpdate');
        // propsとstateの前後の状態を比較して再描画をコントロール
        if (this.helloTitle === nextState.helloTitle) {
            // 差分がないので無駄な再描画をしない
            return false;
        }
        return true; 
    }

    // 廃止予定
    componentWillUpdate() {
        alert('⑥componentWillUpdate');
    }

    componentDidUpdate() {
        alert('⑦componentDidUpdate');
        // 変化後のDOMを処理したい場合など
    }
    componentWillUnMount() {
        alert('⑧componentWillUnMount');
        // コンポーネントがDOMから削除される直前に実行される
        // 関連するイベントの後片付け的な処理やタイマーのキャンセルなど
    }
    changeText() {
        // 自コンポーネントのイベントにより状態を変更
        this.setState({ helloTitle: 'Hello World!!!!!!' } );
    }
}

export default Hello;

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0