😸

wip [note]react-official-document

2022/02/13に公開

https://ja.reactjs.org/docs/getting-started.html

what is react

React is a JavaScript library for building user interfaces, developed by Facebook and the community.

前提となる知識

JavaScript 言語の基本的な理解があること

JSX の導入

const element = <h1>Hello, world!</h1>;

これは JSX と呼ばれる JavaScript の構文の拡張
UI がどのような見た目かを記述するために、React とともに JSX を使用することが推奨されている
テンプレート言語ではなく、JavaScript の機能を全て備えたもの
JSX は React “要素” を生成する

jsx基礎文法

  1. reactライブラリをimportする
  2. return文の中がjsx気泡
    • 基本的にはhtmlと同じ
    • classはclassNameに
import React from "react";

interface Props {
  num: string;
}

class Sample extends React.Component<Props> {
  render() {
    return <p>{this.props.num}つ目のコンポーネント</p>;
  }
}

export default Sample;

特殊なjsx構文

  1. jsxは必ず階層構造(最上位のコンポーネントは並列にできない)
  2. React.Fragmentで囲む(htmlとして出力されない、divタブ等必要のないタグを避けれる)
  3. React.Fragmentは省略でかける
  render() {
    return (
      <React.Fragment>
        <p style={{ color: "pink", fontSize: "30px" }}>Dandyyy</p>
        <Sample num={"5"} />

        <p>{this.state.message}</p>
        <button onClick={this.handleClick}>ボタン</button>
        <p>{this.state.counter1}</p>
        <button onClick={this.doAction1}>Click</button>
      </React.Fragment>
    );
  }
}

JSXを使う理由

  • 以下の表示のためのロジックを実現する

    • イベントへの応答や経時的な状態の変化、画面表示のためのデータを準備する方法といった、他の UI ロジックと本質的に結合したもの
  • マークアップとロジックを別々のファイルに書いて人為的に技術を分離するのではなく、React はマークアップとロジックを両方含む疎結合の「コンポーネント」という単位を用いて関心を分離

  • JSX があるために React は有用なエラーや警告をより多く表示することができ

JSX に式を埋め込む

name という変数を宣言して、それを中括弧に囲んで JSX 内で使用

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

ReactDOM.render(
  element,
  document.getElementById('root')
);

formatName(user) という JavaScript 関数の結果を<h1>要素内に埋め込んでい

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

JSX もまた式である

if 文や for ループの中で使用したり、変数に代入したり、引数として受け取ったり、関数から返したりすることができる

JSX で属性を指定する

文字列リテラルを属性として指定するために引用符を使用できます。

const element = <div tabIndex="0"></div>;

属性に JavaScript 式を埋め込むために中括弧を使用することもできます。

const element = <img src={user.avatarUrl}></img>;
警告:

JSX は HTML よりも JavaScript に近いものですので、React DOM は HTML の属性ではなくキャメルケース (camelCase) のプロパティ命名規則を使用します。

JSX では例えば、class は className となり、tabindex は tabIndex となります。

JSX で子要素を指定する

タグが空の場合、XML のように />でタグを閉じる事ができます:

const element = <img src={user.avatarUrl} />;

JSX のタグは子要素を持つことができます:

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

JSX はインジェクション攻撃を防ぐ

JSX にユーザの入力を埋め込むことは安全です:

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

デフォルトでは、React DOM は JSX に埋め込まれた値をレンダー前にエスケープする
このため、自分のアプリケーションで明示的に書かれたものではないあらゆるコードは、注入できないことが保証されます。レンダーの前に全てが文字列に変換されます。これは XSS (cross-site-scripting) 攻撃の防止に役立ちます。

JSX はオブジェクトの表現である

Babel は JSX を React.createElement() の呼び出しへとコンパイルします。

以下の 2 つの例は等価です:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement() はバグの混入を防止するためにいくつかのチェックも行いますが、本質的には以下のようなオブジェクトを生成します:

// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

このようなオブジェクトは “React 要素” と呼ばれます。これらは画面に表示したいものの説明書きとして考えることができます。React はこれらのオブジェクトを読み取り、DOM を構築して最新に保ちます。

要素のレンダー~React 要素を DOM に変換する~

要素とは React アプリケーションの最小単位の構成ブロック

要素を DOM として描画する

HTML ファイルの中に<div>要素があったとしましょう

<div id="root"></div>

この中にあるもの全てが React DOM によって管理されることになるので、“ルート” DOM ノードと呼ぶ

React だけで構築されたアプリケーションは、通常ルート DOM ノードをひとつだけ持つ
既存のアプリに React を統合しようとしている場合は、独立したルート DOM ノードを好きなだけ持つことができる

React 要素をルート DOM ノードにレンダーするには、その 2 つを ReactDOM.render() に渡します:

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

レンダーされた要素の更新

React 要素はイミュータブル

  • 一度要素を作成すると、その子要素もしくは属性を変更することはできない
  • 要素は映画の中のひとつのフレームのようなものであり、それは特定のある時点の UI を表す

UI を更新する唯一の方法は、新しい要素を作成して ReactDOM.render() に渡すこと

React は必要な箇所のみを更新する(仮想dom)

React DOM は要素とその子要素を以前のものと比較し、DOM を望ましい状態へと変えるのに必要なだけの DOM の更新を行います。

毎秒ごとに UI ツリー全体を表す要素を作成しているにも関わらず、内容が変更されたテキストノードのみが React DOM により更新されます。

?
私達の経験上、時間の経過によりどのように UI が変更されるかを考えるよりも、任意の時点において UI がどのように見えるべきかを考えることで、あらゆる類のバグを排除することができます。

wipコンポーネントと props

コンポーネントにより

  • UI を独立した再利用できる部品に分割し、部品それぞれを分離して考えることができるようになる
  • このページではコンポーネントという概念の導入を行います。詳細な API リファレンスはこちらで参照できます。(https://ja.reactjs.org/docs/react-component.html)
    • 概念的には、コンポーネントは JavaScript の関数と似ています。(“props” と呼ばれる)任意の入力を受け取り、画面上に表示すべきものを記述する React 要素を返す

関数コンポーネントとクラスコンポーネント

https://www.twilio.com/blog/react-choose-functional-components-jp#:~:text=何よりも明確な違い,renderメソッドを含みます。
Reactの世界では、Reactコンポーネントの記述方法が2つあり
関数を使用する方法と、クラスを使用する方法て
最近では関数コンポーネントの使用が増えている

関数コンポーネントとクラスコンポーネントの違い
それぞれの名前が示すように、関数コンポーネントはJSXを返すプレーンなJavaScript関数で、クラスコンポーネントはReact.Componentを拡張するJavaScriptクラス

関数コンポーネントが主流になる

  • 関数コンポーネントの記述は短くシンプルです。つまり、開発、理解、テストがしやすいということです。クラスコンポーネントではthisが多用されるため混乱が生じやすいですが、関数コンポーネントを使用すれば、このような混乱を回避して、すべてを簡潔にしておくことができ
  • Reactチームはクラスコンポーネントに置き換わる(さらにはそれを上回る)機能コンポーネント用Reactフックのサポートに力を入れており、利用可能なReactフックが増えていることもポイント
    • 関数コンポーネント用の新しいフックとしてuseStateやuseEffect

コンポーネントのレンダー

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

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

流れ

  1. <Welcome name="Sara" /> という要素を引数として ReactDOM.render() を呼び出します。
  2. React は Welcome コンポーネントを呼び出し、そのときに props として {name: 'Sara'} を渡します。
  3. Welcome コンポーネントは出力として <h1>Hello, Sara</h1> 要素を返します。
  4. React DOM は <h1>Hello, Sara</h1> に一致するよう、DOM を効率的に更新します。

コンポーネントを組み合わせる

コンポーネントは自身の出力の中で他のコンポーネントを参照できます。これにより、どの詳細度のレベルにおいても、コンポーネントという単一の抽象化を利用できます。

  • ボタン
  • フォーム
  • ダイアログ
  • 画面

React アプリでは、これらは共通してコンポーネントとして表現されます。

例えば、Welcome を何回もレンダーする App コンポーネントを作成できます:

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

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

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

典型的には、新規の React アプリは階層の一番上に単一の App コンポーネントを持っています。しかし、既存のアプリに React を統合する場合は、Button のような小さなコンポーネントからボトムアップで始め、徐々にビューの階層構造の頂上に向かって進んでいってもよい

コンポーネントの抽出(より小さなコンポーネントに分割)

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

これは props として

  • author(オブジェクト)
  • text(文字列)
  • date(日付)

を受け取り、ソーシャルメディアサイトにおける 1 つのコメントを表し

これだけのネストがあるため、このコンポーネントの変更には苦労を伴い、また内部の個々の部品を再利用することも困難です。ここからいくつかのコンポーネントを抽出

Avatar を抽出

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

Props は読み取り専用

state とライフサイクル

もちろんアプリケーションの UI は動的で、時間に応じて変化するものです。state により React コンポーネントは上述のルール(全ての React コンポーネントは、自己の props に対して純関数のように振る舞わねばなりません。:React は柔軟ですが、1 つだけ厳格なルール)を壊すことなく、時間と共にユーザのアクション、ネットワークのレスポンスや他の様々な事に反応して、出力を変更することができます。

関数をクラスに変換する

クラスにローカルな state を追加する

クラスにライフサイクルメソッドを追加する

イベント処理

  • React のイベントは小文字ではなく camelCase で名付けられている
  • JSX ではイベントハンドラとして文字列ではなく関数を渡す
  • React では false を返してもデフォルトの動作を抑止することができない

html

<button onclick="activateLasers()">
  Activate Lasers
</button>

react

<button onClick={activateLasers}>
  Activate Lasers
</button>

Discussion