React勉強の記録

更新日時: April 28, 2020

Reactの目的は?

  • 単一のJavaScriptライブラリ

  • 画面に表示される有用なコンテンツ(HTML)を作る

  • インタラクティブな処理をする

reactでよく書いているclassは?

  • JavaScriptのclass(ES2015)

    • アロー関数、インスタンス属性、class属性など
  • ReactのComponentを使うことは、Reactの一番基本的な部分の1つ

HTMLみたいに書いているものは?

  • JSX

  • HTMLではない

  • React Componentがレンダリングされ、画面に表示されるときの形を指している

  • でも、HTMLの書き方に近いところはある

※Reactを書く上でJSXの書き方を覚えるのは必要

画面内で動きを出したいときは?

  • event Handler

  • ユーザとアプリのインタラクティブなアクションを感知してアプリやComponentを更新したり、表示することができる

reactとreact-domを別々で使う理由は?

  • reactでは各Componentを定義するJavaScriptのコードが含まれている

  • つまり、reactはライブラリ全体のプロセスがちゃんと動くことを担当する

  • react-domはreactで書いたComponentをDOM内部に表したり、HTMLとして表したりする

  • react、react-domはそれぞれ「Componentの定義に使う」「画面へComponentを表すために使う」

create-react-appでReactのプロジェクトを立てる

大きな流れ

  • Install / Update Node JS

  • Install create-react-app

  • Generate a project

  • Build project

実行環境

  • node v12.14.1

  • npm 6.14.4

  • yarn 1.22.4

Reactのプロジェクト生成の方法

npx create-react-app {appname}

もし、すでにグローバルでcreate-react-appがインストールされている場合は以下のコマンドを実行する必要がある

npm uninstall -g create-react-app

Mac/Linuxの場合、以下のコマンドも実行する必要がある

rm -rf /usr/local/bin/create-react-app

npxインストール時

npxインストール時に

react@16.13.1

react-dom@16.13.1

react-scripts@3.4.1

cra-template@1.0.3

がインストールされる

Reactプロジェクト下で使うコマンド

Reactのプロジェクト内で以下のコマンドで実行が可能

yarn start

開発用のサーバを開始する。

yarn build

製品版のための静的ファイルをバンドル(1つのファイルに束ねる)する。

yarn test

テストランナーを起動する。

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!

Reactプロジェクトをインストールしたときに注目しておく依存関係

Babel

  • ES5以降、毎年更新されているJavaScriptのバージョン(ES2018,ES2019…)があり、バージョンが上がるたびに良い機能が追加されていく

  • できるだけ新しいバージョンを使いたいが、最終的にはユーザのブラウザでも実行されるように保証しなければならない

  • しかし、ユーザが必ずしも最新のブラウザを使っているとは限らない

  • ES5はすべてのブラウザでサポートされており、最新のJSのバージョンになるにつれ、ブラウザによっては保証されない可能性が高くなる

  • つまり、ユーザに使ってもらうことを前提に作るためには後方互換性を意識しなければならない

  • そこで、前のバージョンでも動作できるようにJSのソースコードをES5の書き方に変える必要がある

  • その変換(トランスパイル)をやってくれるのがBabel

  • ES5に書き換えると、前のバージョンでしか動作しないブラウザであってもJSの動きが保証されることになる

  • そして、create-react-appを実行するとBabelがデフォルトで含まれている!

webpack

  • 複数のJavaScriptファイルを1つにして、圧縮する

  • Component内でimportするときに.jsの指定をしなくても自動でファイルを探そうとすることができる

Dev Server

create-react-appフォルダーの中について

  • src

    • 作成したソースコードを入れるところ
  • public

    • 変更されない静的ファイルを保存するところ
  • node_modules

    • プロジェクトの依存関係がすべて含まれているところ

    • 手動でnode_modulesをいじる必要はない

  • package.json

    • プロジェクトの依存関係と構成を書くファイル
  • package-lock.jsonもしくはyarn.lock

    • インストールされたパッケージの正確なバージョンが書かれているファイル

JavaScriptのModuleシステムについて

  • webpackのバンドルシステムを使う

  • アプリケーションに必要なすべてのModuleをマッピングし、その結果物として1つ以上のバンドルを生成する

  • Moduleの辞書的意味はプログラムを機能ごとに分割した論理的な一部分

  • webpackにおいてはJavaScriptアプリケーションを構成する機能を分割した単位で考えても良い

  • import文を使うと他のファイルで定義したModuleをそのまま使うことができる
    // a.jsで定義
    export function sayHello(){
    console.log('Hello');
    }
    
    // index.js
    import { sayHello } from './a.js';
    sayHello();
    
  • Module単位で書くことによって、別のところで書いたコードを他のコードとの依存性や衝突を気にせず、共有することも可能になった

[Webpack] 사내 webpack 도입기 (2) - webpack 이란? - 오늘의 기억

  • ES2015以前のコードではCommonJS Modulesの書き方を見かけていたのかもしれない

  • しかし、ES2015 Modulesを使うのであれば、importで十分

    // CommonJS Modules
    const React = require('react');
    
    // ES2015 Modules
    import React from 'react';
    

import - JavaScript | MDN

componentについて

  • componentはFunctionもしくはClassでできている

  • componentはHTMLを生成してユーザに見せる

    • この時、書き方はJSXを使う
  • componentはユーザのフィードバックを処理する

    • この時、Event Handlerを使う

Function Componentについて

// こんな感じのComponent
const App = function () {
  return <div>Hi there!</div>
};

//アロー関数で書くとこんな感じ
const App = () => {
  return <div>Hi there!</div>
}

componentをレンダーリングするためにやること

  • reactで作ったページへアクセスするたびにpublic/index.htmlへ移動する

  • reactで生成されたアプリケーションの規則として、idがrootになっているdiv内でComponentをレンダリングする

  • ReactDOM.renderの引数は以下のように設定する

    • 第1引数 : Reactコンポーネントへの参照

    • 第2引数 : React要素をレンダーするためのDOM

JSXについて

  • JSXはHTMLのように見えるが、HTMLではない

  • 前提として、ES2015以降の形式で作成されたJSファイルはBabelを使うことでES5環境のブラウザでも動かすことができるようになること

  • わたしたちのブラウザでは<App />のような書き方のタグが事前に用意されているわけではない

  • それでもブラウザが認識してくれるのは、JSX形式で書いたコードがユーザのブラウザに送られたとき、正常に動作するJSとして変換されるから

  • 正確には、JSXは見た目こそHTMLに近いものの、インポートしたReactライブラリ内の独自に定義された関数を呼び合うことでJavaScriptの制御をしている

    • その上、Babelを通すとES5環境のブラウザでも動かせるように変換してくれる
  • まとめると

    • JSX形式で書くことはちょっと特殊なJavaScriptを書くこと

    • ブラウザはJSX形式で書いたコードを理解しているわけではなく、ブラウザで動かすときにJavaScript形式へ変わる

      • インポートしたReact,ReactDOMのライブラリ内でDOMを生成したり、イベントをハンドリングしたりする
    • その上、Babelを通すとES5環境のブラウザでも動かせるように変換してくれる

  • Babel公式ホームページのTry it outからReactのコードがどうやってES5のJavaScriptへ変わるのかが試せる

  • JSXはReact.createElement(component, props, ...children)のsyntax sugar

  • 子要素を持たない場合、自己クローズ(self-closing)タグを利用することができる
    <div className="sidebar" />
    
  • 子要素がある場合、開始、終了タグを使う
    <Parent>
      <Child />
    </Parent>
    

JSXとHTMLの違いについて

  • 普通にHTMLの書き方でJSXを書くとエラーが発生する

  • 理由は以下

    • JSX独自の属性がある

      • 要素にカスタムスタイルを追加すると違う文法になる

      • 要素にクラスを追加すると違う文法になる

    • JSXはJavaScriptの変数を参照できる

Componentの3要素

  • Componentの入れ子構造(Nesting)

    • Componentは別のComponentの内部に表示できる

    • exportで他のComponentでも使えるようにできる

  • Componentの再利用性(Reusability)

    • アプリケーション全体で簡単に再利用できるに作る
  • Componentの構成(Configuration)

    • Componentが作成されたとき、構成できるものにする

Component命名規則

  • 基本的にパスカルケース(pascal case)で命名する

    • ファイル名、使用するComponent名の両方とも

    • ex)PascalCase、ComponentSystem

カスタムしたComponentを他のComponentで使用するためにやっておくこと

  • 使われる側のComponentにexport処理を書く

  • 使う側のComponentにimport処理を書く

ComponentをJSX構文でレンダリングするためには

// 基本的な型
<Component名 />

入れ子状態でComponentを渡す方法

  • Component自体や使いたいデータを引き渡すときに使う

  • 親Componentタグで子Componentを囲む
    <Parent>
      <Child />
    </Parent>
    
  • 親Componentから子Componentを使う場合、props.childrenで子Componentを扱うことができる
    const Parent = (props) => {
      return (
        <div>props.children</div> //ChildのComponent自体
      );
    };
    
  • 親Componentから子Componentのプロパティを使う場合、props.children.propsで使うことができる
    const Parent = (props) => {
      return (
        <div>props.children.props.参照したい値のキー</div>
      );
    };
    

JSX を深く理解する – React#子要素としての JSX 要素

React基本(入れ子のコンポーネント) - Qiita

関数ComponentとクラスComponentの違い

  • 関数(Functional)Component

    • Good for simple content

    • 渡されたデータを元にJSXの生成をするような簡単な処理を書くときに使う

    • 複雑ではないロジックでComponentを作る時に使う

    • レンダリングされるデータを固定する

      • レンダリングされるまでデータを維持する
  • クラス(Class)Component

    • Good for just about everything else

    • ネットワークの通信が必要だったり、データの加工が必要だったりする処理を書くときに使う

    • 簡単ではない、複雑なロジックでComponentを作る時に使う

クラスComponentを使う利点

  • (一般的に、)コードを構成することが簡単になる

    • ファイル内のコードを見て何をするためのComponentなのかがエンジニアの視点からして分かりやすくなる
  • stateが使える

    • インタラクティブなアプリケーションを作る上で必要な部分

    • ユーザの入力値を処理するときに使う

    • 非同期処理の機能が扱える

  • Life Cycle Eventを理解するにもメリットがある

クラスComponentの原則

  • JavaScriptのClassを使うこと

    • ES2015から導入されたあのClass

    • PrototypeというOOPで使われるイメーしするClassとは若干違う

      • でも、大体はOOPに近い
  • React.Componentを継承する

    • React.Componentをサブクラス化するとも言う

    • React.Componentの機能を借りる

  • renderメソッドを定義し、JSXでリターンする

stateの原則

  • クラスComponentでしか使えない

  • propsとstateで混同するかもしれない:(

  • ‘State’はComponentに関連する一定のデータを含んだJavaScriptオブジェクト

  • Componentのstateを更新すると、Componentがほぼ即座に再レンダリングされる

    • setStatestateを更新するとrenderメソッドが再度呼び出される

    state とライフサイクル – React

    • Componentのリレンダリングをすることは、stateを更新することを意味する
  • Componentが生成された時、stateを初期化する必要がある

    • constructorが使える

      • インスタンスが生成される度に呼ばれる

      • Componentのインスタンスが画面に表示されると最初に呼び出される

      • 必須ではないが、Componentの最初のレンダリングで、初期値の設定がしたい場合に使えば良い

      • stateも初期値の設定はできる

      • super関数を使うことで親(React.Component)のconstructorに対する参照ができる

        super - JavaScript | MDN

        • superを使ってはじめてthisが使える

          • もし、superをする前にthisを使うと親クラスで定義されているはずのプロパティを使う事なんてできない
            //親クラス
            class Parent {
              constructor(lastName) {
                this.lastName = lastName;
              }
            }
            
            //子クラス
            class Child extends Parent {
              constructor(lastName) {
                this.introduction(); // constructorで呼び出された時点ではthisが定義されていない
                super(lastName);
              }
            
              introduction() {
                return `My last name is ${this.lastName}.`;
              }
            }
            
          • このようなことが起きないようにするため、superで親クラスを呼び出し、thisオブジェクトが使えるようにする

          なぜsuper(props) を書くの? - React界のカリスマ「Dan Abramov」のブログ - Qiita

          なぜsuper(props) を書くの? — Overreacted

        • これにより、propsに入っているデータをReactのComponent内で使うことができる

  • stateがsetState関数を使用してのみ更新できる

    • 例外があるとしたらconstructorのthis.stateで初期値を設定するときのみ

propsの語源

  • properties(特性、属性)の略

  • propagation(伝播)の意味合いも間違ってはない

propsの使い方

  • immutable data(不変のデータ)

  • can’t change it(変更不可)

  • passed in from parent(親から渡される)

  • can be defaulted & validated(デフォルト値の設定と検証が可能)

  • Componentを使う際に、内部で変更されないデータを保存するときに使う

  • 2つのプロセスがある

    • 1つ目は、データをComponentへ提供する

    • 2つ目は、渡されたデータを使う

  • 一般的に、親Componentから子Componentに渡される値

    • 子Componentをカスタマイズしたり、構成したりするのが目的

    • Componentの見た目、インタラクティブなアクションを設定する

    • 子Componentから親Componentにpropsを直接的に渡すことはできない

    • 慣習的にpropsで受け取る

  • getDefaultPropsで定義されたデフォルト値か、親Componentから渡された値のどちらかをもつ

  • クラスComponent内で扱うときは、this.propsで書く

state とライフサイクル – React

propsthisの扱いの違い

  • propsは不変の値

  • thisは変更可能な値

    • thisがクラスに存在する目的

    • render、ライフサイクルメソッドを呼び出した時、更新された値を読み込める

  • 視覚的に見えるComponentがレンダリングされる時、イベントハンドラーも一緒に含まれる

    • つまり、イベントハンドラーがあるpropsとstateを持ってrenderに属されること

    • だが、クラスComponentの場合、this.propsがrenderに属されなくなる

함수형 컴포넌트와 클래스, 어떤 차이가 존재할까? — Overreacted

stateの使い方

  • mutable data(可変のデータ)

  • can change it(変更可)

  • maintained by component(コンポーネントによって保持)

  • should ne considered private(プライベートであるべき)

  • stateの変更は、仮想DOMとの差分から実際のDOMを更新してComponentを再描画するために使われる

  • UIに関連した状態(pulldownの状態のような)、外部のデータに関連する状態(ログイン中のユーザ情報みたいな)になることがある

    • 外部からデータを取得してから表示するケースがこれに当たる

    • データを取得する前にすでにJSXでレンダリングされる画面から、それ以降に更新されたデータの結果を反映させないといけないときにstateが使われる

    • 非同期処理でデータをレスポンスするまで待つ処理時に使われる

    • リレンダリングするときに使われる

  • Component内でthis.setState()を呼び出して状態を更新することができる

Life Cycle Method

constructor
1回限りのセットアップを行う
公式コミュニティの慣習としてデータ読み込みの処理はここに書かずcomponentDidMountに書くことを推奨する

render
画面にコンテンツを表示する
JSXを返す以外何もしない

componentDidMount
この関数はComponentが最初に画面にレンダリングされるときに1回だけ自動的に呼び出される
初期データ読み込みを行うときに使われる
※「初期データ読み込み処理をここでやるという明快な役割が決められる

componentDidUpdate
Componentが更新されるたびに自動的に呼び出される
技術的にcomponentDidUpdateの実行前にrenderが一度実行されJSXを返して画面に表示する処理が走る
state/propsが変わってデータ読み込みをするときに使われる
ユーザからの入力値外部からのデータ読み込みなどを含めたComponent内の更新があったらここでやる

componentWillUnmount
Componentをそれ以上表示しない場合に呼び出される
React以外のものを片付けるときに使われる

まれに使われるメソッド
shouldComponentUpdate
getDerivedStateFromProps(最初のマウント時更新時にrenderされる直前に呼ばれる)
getSnapshotBeforeUpdate

React.Component – React

state初期化に代替できる書き方

  • 普通に書くと、以下のようになる
    class App extends React.component {
      constructor(props) {
        super(props);
    
        this.state = { 初期化したい内容 };
      }
    
    }
    
  • ただ、BabelがES5以下の環境でも動かせてくれるように変換することを利用し、constructorなしでも書ける
    class App extends React.component {
      state = { 初期化したい内容 };
    
    }
    
    • 良いところは、コードの量が減らせること

stateを親Componentから子Componentにpropsとして渡す

  • 親Componentでthis.stateに指定した値を子Componentにpropで渡す
    //親Component
    
    this.state = { key:value }
    
    render(){
      return <Child passKey={this.state.key} />
    }
    
    //子Component
    const Child = (props) => {
      return (
        <div>props.passKey</div>
      )
    }
    

イベントハンドラーの入力値を受け取る方法

  • onClickonChangeonSubmit

    • 引数はeventのようにイベント発生による引数であることを明示的に表す
  • 行いたい処理を書いた関数をthisで指定してイベントハンドラーに渡せば変化がイベントの変化が起きたときにコールバックする
    onInputChange(event) {
      
      行いたいしたい処理
      
    }
    
    render(){
      return(
        <div>
          <input onChange={this.onInputChange}>
        </div>
      )
    }
    
  • 無名関数をワンライナーで書くこともできる
    render(){
      return(
        <div>
          <input onChange={(event) => console.log(event.target.value)}>
        </div>
      )
    }
    

レコードを表示する方法

  • map関数で表示する

雑学

  • node_modules配下にあるライブラリ構成を見るとcjsフォルダーで区切られていることがあるが、CommonJSの略のように見える

.mjs とは何か、またはモジュールベース JS とエコシステムの今後 | blog.jxck.io

  • ESMはECMAScript Modulesの略

Node.jsのECMAScript Modulesの紹介 - 技術探し

複数のモジュール形式(CommonJS, ES Modules, UMD)をサポートしたnpmパッケージの作り方 in TypeScript - dackdive’s blog

JavaScript モジュールの現状 | POSTD

  • webpackでnode_modulesを1つのファイルとする過程が気になる場合は読む

Webpackでnode_modulesを1つのファイルにする – Mzlog 水島企画

Tips

  • HTMLのclassforはJSXではclassNamehtmlForになる

    • 理由は、JSXでも同じ使われる予約語であるため
  • JSX構文において中括弧で囲むセット数によって、表現することが違う。

    • 1セット : JavaScriptの記述ができる

      • 「JavaScriptの変数を参照する」という意味

      • 変数を直接指定したり、演算式を書いたりすることができる

        const text = "Hello world";
        ReactDOM.render(
          <div>
            <h1> {text} </h1>
            {1+2+3}
          </div>
          ,document.getElementById('root')
        );
        
    • 2セット : オブジェクト技法でデータをセットできる

      • HTMLのように直接style属性を指定する場合は、{ { } }(double curly braces)を使ってオブジェクト技法で指定する

      • つまり、JavaScriptの記述 + オブジェクトのセットのように覚えればいい

        <a style=>Hello, world</a>
        
    • 3セット : HTMLエスケープをしないオブジェクト技法

      • 2セットではHTMLの特殊文字コードへ変換されてしまうHTMLエスケープが防げる
        //オブジェクト
        { "name": "<b>Hello</b>"}
        
        //2セット状態
              
        
        &lt;b&gt;Hello&lt;/b&gt;
        
        //3セット状態
        }
        
        <b>Hello</b>
        

mustache記法について簡単にまとめてみた - Qiita

JSXの基本 – React入門 - to-R Media

javascript-React의 JSX 구문에서 이중 중괄호의 목적은 무엇입니까? - 스택 오버플로

  • 要素のstyleをインラインで直接指定する場合、CSSのケバブケース(単語をハイフンでつなぐ)をキャメルケース(単語の先頭が大文字)に変更する必要がある

    • style指定時、key:value形式のvalueの方は、必ず文字列にする

React CSS

PropTypes を用いた型チェック – propsのデフォルト値

  • 要素の2つの属性

    • Controlled

      • state管理されている

      • Reactの世界の中でデータが管理されている

      • rerenderされてもReactの管理下でデータが保持される

      • HTMLタグにReactで管理しているデータをオーバーライトする

    • UnControlled

      • state管理されていない

      • HTMLの世界のタグの中でデータが管理されている

      • rerenderされたら消える可能性がある

  • Virtual DOMによるkey指定について

    • リスト表示の際に、その要素がユニークであることを示さないといけない

    • APIのresponseによっては固有のidも添えて送られる場合があるのでそれを使用する

    • returnさせる時、個々の要素の一番ルートにidを指定しておく必要がある

  • React Refs

    • 単一のDOM要素へのアクセスを提供する

    • コンストラクターで参照を作成し、インスタンス変数に割り当て、特定のJSX要素にプロパティとして渡す

    • 一個一個の独立した要素に対して個別の設定や処理をさせたいときに使う

      class A extends React.Component {
        constructor(props) {
          super(props);
      
          this.Ref = React.createRef();
        }
      
        render() {
          return (
            <div>
              <img ref={this.Ref} />
            </div>
          );
        }
      }
      

Ref と DOM – React

  • props/state/Component概念

Reactの基礎(JSX, ライフサイクル, state, props) - わくわくBank

컴포넌트에 함수 전달하기 – React

React 최상위 API – React

  • props.childrenについて

    • 子要素に対して共通の設定を指定する場合は、props

    • 子要素に対してそれぞれ違う設定を指定する場合は、props.children

Reactで複数のchildrenを扱いたい場合の実装パターン - Qiita

props.childrenを渡す方法 - Qiita

Reactのchildren探訪 - Qiita

コンポジション vs 継承 – React

styled-components

styled-componentsを使ったCSS設計 - Qiita

styled-components: Basics

コメントする