Help us understand the problem. What is going on with this article?

Reactの基礎を学ぶ

前提

可能な限りES6の記載で説明している(はず

Reactって

  • View部のみ担当するライブラリ
  • 仮想DOMにより、余計なレンダリングが発生しない

環境

環境作成

公式見ると、create-react-app使いなさいって感じなので入れる。
https://github.com/facebookincubator/create-react-app

create-react-appインストール
npm install -g create-react-app
プロジェクト作成
create-react-app プロジェクト名

ローカルサーバ起動

cd プロジェクト名
npm start

この状態で
http://localhost:3000/
を開くと、
Reactの初回画面が表示される。

ファイル編集用のエディタ(Atom)

①Atomインストール
https://atom.io/

②gitもいれたほうがいい

③日本語化
「file」→「Setting」→「install」→「japanese-menu」インストール

④入れると捗るパッケージ
autocomplete-paths
convert-to-utf8

⑤React用に捗るパッケージ
react
Atom-beautify

JSXを知ろう

JSXって

Reactは、仮想のDOMを駆使して、望む結果を最終的に表示する。

その過程をHTMLっぽく記載できる方法がJSX。
※HTMLではないので注意

特徴としては、

  • HTML5のタグはすべてつかえる
  • カスタムコンポーネントをタグ名として使える
  • JavaScriptに比べて構造がわかりやすい

などがある。

JSXのわかりやすさを知る

例えば、
「h1タグを用意したい」
とき

素のJavaScript
React.DOM.h1({className: 'question'}, '質問');
JSXなら!
<h1 className="question">質問</h1>

 
ちなみに上記をカスタムコンポーネントとして作成すれば

<App>質問</App>

こんな記述もできるように。

JSXとHTMLの違い

①JSX独自の属性がある
key、ref、dangeroslySetInnerHTML

②使えない属性もある
class、forは、JavaScriptでも使われるため、属性として使用できない。
以下のように置き換えて使うこと。

HTMLの場合 JSXの場合
class className
for htmlFor

属性値にオブジェクトを渡す

プロパティ名がキャメルケースのオブジェクトを属性値として
渡すことが可能。

var styles = {
  borderStyle: "#999",
  borderThickness: "1px"
};



/* JSX部 */
<div style={styles}>・・・</div>
/* JSX部 */

コンポーネントを知ろう

コンポーネント?

個人的なイメージで説明すると、

  • JSXで表現されたタグ
  • 親タグとその子孫タグ

がコンポーネント。

これも
<div></div>
これも
<div><h1>title</h1></div>
1コンポーネントとしての扱い。

カスタムコンポーネント

状況に応じて表示を変える自作のタグ。
実態はJavaScriptのコード。

下記は広義でコンポーネント、狭義だとカスタムコンポーネント。
<Custom></Custom>

コンポーネントでなにするの?

カスタムコンポーネント内のJSXで、
更に別のカスタムコンポーネントを表示。
そのカスタムコンポーネント内のJSXで、またカスタムコンポーネント・・・

といったことを繰り返して、Reactとしての画面描画を行う。

コンポーネント例

create-react-appで作成したプロジェクトを
もうちょっと簡易にした例を参考に、流れを把握しよう。

関係者

./
public/ index.html
src/ index.js
App.js
コンポーネント作成例(App.js)
//必須
import React, { Component } from 'react';

//Appクラス = Appコンポーネント(カスタムタグ)
class App extends Component {
  render() {
    return (
      //returnの中にJSXを記載
      <div className="driver">
        <h2>質問</h2>
      </div>
    );
  }
}

//他の場所で読み込んで使えるようにexport
export default App;
コンポーネント呼び出し例(index.js)
//必須
import React from 'react';
import ReactDOM from 'react-dom';

//コンポーネント読み込み
import App from './App';

//(id="root"のところに)描画
ReactDOM.render(
  <App />,
  document.getElementById('root')
);
index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>React App</title>
  </head>
  <body>
    /* ↓この中に描画される */
    <div id="root"></div>
  </body>
</html>

動的な値を埋め込める

波括弧で変数をJSXの中に埋め込んだりできる。

App.js
class App extends Component {
  render() {
    var text = '質問';

    return (
      <div className="driver">
        <h2>{text}</h2>
      </div>
    );
  }
}

子ノードの受け取り方

<App>質問</App>

こんなJSXがあったとして、
Appコンポーネントでは、その子ノード(ここでは質問というテキスト)を
「this.props.children」で受け取ることができる。

コンポーネントを使いこなすための追加知識

props

コンポーネントのプロパティのこと。

コンポーネントが自己を表現する時に使えるものといえば
プロパティしか無いですよね。

カスタムコンポーネントは
プロパティをpropsというオブジェクトで参照できるようにして、
その状態を見て、自身の描画を変える。

propsを設定

var hoge = [{text: '質問' }];

~

/* JSX */
<List value={hoge} />
/* JSX */

関数も渡せる。

propsの参照

this.props
で行う。

propsの変更や更新

禁止禁止!

親コンポーネントから受け取ったものを変更するなんて、
過去改変して自己の存在を変えるようなものだぞ・・!

propsのデフォルト値

defaultProps(prototypeプロパティ)で設定する。

class App extends Component {
  render() {
    //propsの参照
    var text = this.props.text;

    return (
      <div className="driver">
        <h2>{text}</h2>
      </div>
    );
  }
}

//prototypeプロパティで設定
App.defaultProps = {text: '質問'};

propsのバリデーション

ES6では、propTypes(prototypeプロパティ)で、
ES6以前は、propTypes(クラス内関数)で、
コンフィグオブジェクトを指定する。

App.propTypes = { num: React.PropTypes.number };

※随時追加

オブジェクト 説明

state

コンポーネントの状態を保持するオブジェクト。

stateを子コンポーネントのpropsとして渡せば、
親コンポーネントの今を、子コンポーネントに伝搬させることになるので、
結果として、画面の(再)描画が行える。

----------------       --------------------------------
|俺今、こんな状況 |    |じゃあ俺コレ使って、自分の表示するわ |
-  -------------       ----- --------------------------
 V                         V

(親)つ  (state | props)  ⊂(子) 

stateの初期化

ES6では、constructor(クラス内関数、後述)で、
ES6以前は、getInitialStateで行う。

constructor(props) {
    //必須
    super(props);

    //初期化
    this.state = {title: 'list'};
}

stateの参照

this.state

stateの変更

this.setState({key: value})
で行う。

状態の変更が発生するので、再描画(render関数)が行われる。
setStateで変更しないと、画面に反映されないということでもあるので、
直接stateをいじるなんてことはしないこと。

イベントハンドラ

コンポーネントに、イベントハンドラを指定できるが、
少しだけ特殊な仕様がある。

記載の流れ

class App extends Component {
  //①イベントハンドラ用関数を定義
  eClick(event) {
    //処理
  }
  render() {
    return (
      <div className="driver">
        /* ②イベント紐付け */
        <input type="button" onClick={this.eClick.bind(this)} value="1" />
      </div>
    );
  }
}

eventについて

イベントハンドラ内で、その発火元の情報を受け取りたい場合、
eventを第1引数でうけとると、そこから抽出が可能。
console.log(event.target.value); //1

bind(this)

ES6以降で、イベントハンドラ内でthis(コンポーネント)を使いたい場合、
constructorかJSX内でthisをbindしないといけない。

<input type="button" onClick={this.eClick.bind(this)} value="1" />
constructor(props) {
  super(props);

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

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

コンポーネントからコンポーネントを呼ぶような作りになってくると、
コンポーネント内のライフサイクルも重要になってくる。

ライフサイクルは、
コンポーネント内で規定の関数、prototypeプロパティで実装してあげると、
所定のタイミングで呼ばれる。

描画まで

動作タイミング 呼ばれる関数等 主な使用目的
初回描画時のみ
初期処理前
defaultProps propsのデフォ値設定。
ES6の場合、prototypeプロパティによる定義で実装。

※ES6以前の場合、getDefaultProps。
初期処理 constructor(props) stateの初期化。
super(props);を記載しなければならない。
このタイミングでthis.propsが使えるようになる。

※ES6以前の場合、getInitialState。
描画直前 componentWillMount
render() 省略不可。仮想Domの作成。
描画後 componentDidMount DOMの操作。

描画中

動作タイミング 呼ばれる関数等 主な使用目的
props変更時 componentWillRecieveProps stateの変更など。
props、state変更時 shouldComponentUpdate falseを返すことで、以降の処理をスキップできる。
描画直前 componentWillUpdate
render()
描画後 componentDidUpdate DOMの操作。

コンポーネント破棄

動作タイミング 呼ばれる関数等 主な使用目的
componentWillUnmount

図示している方がいらっしゃるのでこれがわかりやすいかも。
React component ライフサイクル図

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away