LoginSignup
2
2

More than 3 years have passed since last update.

【React】公式ドキュメントの私的まとめ

Posted at

Reactがマジでわかんない
おそらく買った本がむずすぎた
公式を読んで見ることにした
その私的まとめ

JSXの導入

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

javascriptの拡張言語
使う理由はjavascriptにHTMLを書くようにかけるので直感的にわかりやすい

式の書き方

{}の中に式を書けばいい
JSXは式だだからifにもforにも打ち込める

render

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

上記がHTMLファイルにあるとするとこれルートDOMを言うことにする

React要素をルートDOMにレンダリング(HTMLを人が見れる形にする)するには
React.render()に渡す

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
引数 意味
第1 React要素
第2 ルートDOM

Reactは意味ミュータブル
更新するには新しい要素を作成してReact.render()に渡す
以下の公式のコードには感動した
これは秒刻みで動く時計の例


function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);

もう一度いうと更新するには
新しく要素を作詞→React.render()に渡す、という流れ

React は必要な箇所のみを更新する

これを見たとき楽しくなった。とある本を読んで勉強するよりドキュメント読んだほうが遥かに楽しいし勉強になる。
今後は「入門」という文字の入った本に気をつけよう

話を戻すと先の時計だが、ディベロッパツールで見てみると時刻のとこだけのDOMを変更している

これはとある入門書を見て知っていたが百聞は一見にしかずとはまさにこのこと
理解ができた感動した

componentとprops

コンポーネントで部品を独立したものにして再利用可能にできる

コンポーネントはjavascript関数に似ていてpropsという入力を受け取りReactエレメントを返す
コンポーネントはReactエレメントを返す。
コンポーネントはReactエレメントを返す。
コンポーネントはReactエレメントを返す。

そうだったのか。。
コンポーネントはReactエレメントを返すのか。。

コンポーネントの定義には関数とクラスがある、これは知ってる


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

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

上記コードの説明も丁寧でわかりやすかった

このときコンポーネント名は大文字で始める

import React from 'react';
import ReactDOM from 'react-dom';

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')
);

このコードを見たとき更新かなと思ったが、3行表示された、ああそうだったと、忘れてるなぁと思った

コンポーネント抽出

unction 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>
  );
}

上記コードがコードの分割により以下のようになる

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

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

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}

見やすい、スッキリ

Avatarコンポーネントの作成

このコンポーネントは自身がレンダリングされることを想定していない
propsの名前がuserがるかわれているのは
これはコンポーネント自身の観点で名前をつけることが推奨されているから

長いコードを関数化する作業に似ている

propsは読み取り専用

propsは変更してはいけない
Reactコンポーネントはpropsに対して純粋関数であること

stateとライフサイクル

先の秒刻み時計で進めていく
以下からはClockコンポーネントを再利用可能かつカプセル化されたのにする方法

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

まずは見た目のカプセル化

しかし理想は以下のコードだけを書いてClock自身を更新させたいらしい

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

これの実現にはstateを追加する必要があるという
このstateはコンポーネントによって完全プライベートなもの

関数をクラスに変換

以下の手順でクラスに変換

  1. React.Componentを継承
  2. render()というからメソッドを用意
  3. 関数の中身をそのメソッドの中に書く
  4. render()内のpropsをthis.propsへ書き換える
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

renderメソッドは更新が発生したときに毎回呼ばれるが同一DOMノード内で<Clock />をレンダーしている限り、Clockクラスのインスタンスは1つだけ使われる

つまり同一DOM無いであればいくらrenderメソッド内のClockを呼び出しても同じインスタンスが使われる、保持したものはそのまま使えるということ、かな

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

以下の3ステップでdateをpropsからstateに移す

  1. render()メソッド内のthis.props.datethis.state.dateに書き換える
  2. this.stateの初期状態を設定するクラスコンストラクタを設定
  3. <Clock />要素からdateプロパティを削除

2では親のコンストラクタへのpropsの渡し方に注意
クラスコンポーネントでは常にpropsを引数として親クラスのコンストラクタを呼び出す必要がある

super(props)

とある入門書ではなぜこれを書くのか。
初見でこれを見たときなんで親クラスのを呼び出しているのかわからなかった。
今もなぜだかわからないけどそうおいうものだとわかっただけもスッキリする。

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

コンポーネント破棄時にリソースを開放したほうがいい

タイマー設定は最初にClockが描画(マウント)されるとき。
タイマークリアはClockが生成したDOMが削除(アンマウント)されるとき

このようなライフサイクルメソ度を使っていく

componentDidMount

コンポーネントがマウントされた直後に呼ばれる

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

タイマーIDをthis上に格納しているのには訳がある

componentWillUnmount

コンポーネントがアンマウントされた直後によばれる
このタイミングでクリアするのがいい

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

最後にtick()を作る
コンポーネントがローカルstateの更新をするためにthis.setStateを使う

  tick() {
    this.setState({
      date: new Date()
    });
  }

何が起きたかの振り返り

  1. <Clock />がReactDOM.render()に渡されると.ReactはClockコンポ-ネントのコンストラクタを呼び出す。このときにstateを初期化。
  2. 次にReactはrender()を呼び出す。
  3. Clockの出力されるとReactはcomponentDidMountを呼び出す。
  4. tick()が実行されるとsetStateでstateが変更される。それをReactが感知してrender()を再度呼び出す。そしてthis.state.dataが前回と違っていいるためReactはDOMを更新
  5. Clockコンポーネントが削除されたらcomponentWillUnmountでタイマーが止まる

stateを正しく使用する

stateを直接変更しない

以下は再レンダーされない

this.state.comment = 'Hello';

setStateを使えばいい

this.setState({comment: 'Hello'});

直接書き換えた場合、再レンダリングされない
Reactが変更を検知できないため。

2
2
0

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
2
2