【React】基本

React

Udemyのこちらの学習教材を通して学んだ、Reactの基礎をまとめています。

モダンJavaScriptの基礎から始める挫折しないためのReact入門
Reactの習得に苦戦する理由は「JavaScript」への理解不足です。このコースではスムーズにReact開発のスタート地点に立てるように、モダンJavaScriptの動作の仕組みや概念、機能から解説します。

以前にも以下にまとめていますので、こちらに重複する部分は割愛しています。

Reactの基盤を作成

まずは基盤を作成します。

import React from 'react';

reactって2つ書いてあるけど??

これの意味は、reactというライブラリから、Reactを読み込むという意味

この記述はReact17のアップデートより、JSXの使用だけの場合は記述が不要となりました。

React17のアップデート ???

Reactのアップデート情報はどこから取得すればよいのか?

ここに記載されていました!

Introducing the New JSX Transform – React Blog
Although React 17 doesn’t contain new features, it will provide support for a new version of the JSX transform. In this post, we will describe what it is and ho...

With the new transform, you can use JSX without importing React.

そもそもなぜ必要だったのでしょうか?

JSXに記述したコードがJavaScriptにコンパイルされるのに必要だった。

これが、バージョンアップデートによりデフォルトで機能が組み込まれた。

HTMLにコンポーネントを反映していくのに必要なreact-domをimportして、

Reactの基盤を作成する。

import ReactDom from "react-dom";

// nullという値を返すAppという関数を作成
const App = () => {
  return null;
};

// Appを画面に反映する
// renderという関数を使用する
// 第一引数にAppを設定し、コンポーネントとしてレンダリング
// 第二引数にどこに反映していくかを記述。そしてHTMLのidを指定
ReactDom.render(<App />, document.getElementById("root"));
// これでReact開発の基盤ができる!

ReactではJavaScriptの中(JSX)にHTMLを書いていく。

こんなふうに書くことができる。

const App = () => {
  return <h1>Hello World</h1>;
};

return内の記述が複数行になる場合は、( )で囲って書いていく

const App = () => {
  return (
    <h1>Hello World</h1>
  );
};

一行追加する。

const App = () => {
  return (
    <h1>Hello World</h1>
    <p>How are you</p>
  );
};

こう書くと以下のエラーとなります。

/src/index.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?

これはなぜかというと、returnのHTMLは1つのタグで囲わないといけないというルールがある。

そのためdivタグで囲う。

const App = () => {
  return (
    <div>
      <h1>Hello World</h1>
      <p>How are you</p>
    </div>
  );
};

しかし、このようなエラー回避のためだけにdivを書くのはあまり良くないので、Reactの中のFragmentの使用により同じ役割を果たす事もできる。または空括弧でもOK

const App = () => {
  return (
    <React.Fragment>
      <h1>Hello World</h1>
      <p>How are you</p>
    </React.Fragment>
  );
};

または

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
      <p>How are you</p>
    </>
  );
};

しかし、上記のようにJSXに記述をしていくと、記述量が膨大になってしまう。

そこで、コンポーネント化!

コンポーネントファイルの拡張子は.jsxとする。

するとこんなふうに書くことができる。

import React from "react";
import ReactDom from "react-dom";
import App from "./App";

ReactDom.render(<App />, document.getElementById("root"));

import React from "react";

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
      <p>How are you</p>
    </>
  );
};

export default App;

コンポーネントの命名はパスカルケースとする!

キャメルケースが先頭は小文字であるのに対しパスカルケースは先頭も大文字。

イベントやスタイルを設定するときは、命名をキャメルケースとする。

ボタンクリックでアラートを表示する

onClickButtonという関数をAppコンポーネント内で設定する。

const App = () => {
  const onClickButton = () => alert();
  return (
    <>
      <h1>Hello World</h1>
      <p>How are you</p>
      <button onClick={onClickButton}>ボタン</button>
    </>
  );
};

{ }で囲うことによりJavaScriptを書くことを意味している。

styleの定義の仕方は①直接 と②変数を定義する方法の2つある。

①直接

<h1 style={{ color: 'red' }}>Hello World</h1>

{ }が二重になっているが、styleはオブジェクトで定義するため、内側がオブジェクトの括弧で、外側がJavaScriptを意味している括弧

②変数を定義する方法

const App = () => {
  const cotentStyle = {
    color: 'blue',
    fontSize: '18px'
  };
  return (
    <>
      <p style={cotentStyle}>How are you</p>
    </>
  );
};

CSSもキャメルケースで記述する!

定義位置は、コンポーネントの中のreturnの前

Propsを知る

propsとは、コンポーネントに渡す引数的なもののこと。

ColorfulMessageというコンポーネントを作成し、

App.jsxのJSX内で値を定義し、

ColorfulMessage のコンポーネントで引数propsを定義し、

propsを使って、colorとmessageを変更する。

コードがこちら

import React from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
  const onClickButton = () => alert();
  return (
    <>
      <h1 style={{ color: "red" }}>Hello World</h1>
      <ColorfulMessage color="blue" message="お元気ですか?" />
      <ColorfulMessage color="pink" message="元気です" />
      <button onClick={onClickButton}>ボタン</button>
    </>
  );
};

export default App;

ここでのcolorやmessegeといった変数名は何でも良い。

import React from "react";

const ColorfulMessage = (props) => {
  const cotentStyle = {
    color: props.color,
    fontSize: "18px"
  };
  return (
    <>
      <p style={cotentStyle}>{props.message}</p>
    </>
  );
};

export default ColorfulMessage;

変数propsはなんでもよい。

propsの中には以下が入っているため、props.colorやprops.messageとすることで値を取得することができる。

{color: "blue", message: "お元気ですか?"}
{color: "pink", message: "元気です"}

引数を取得する他の方法

コンポーネントのタグで囲み、.childrenでその値を取得する事もできる。

childrenを使う方法がこちら。

<ColorfulMessage color="blue">お元気ですか?</ColorfulMessage>
<ColorfulMessage color="pink">元気です</ColorfulMessage>

<p style={cotentStyle}>{props.children}</p>

propsの書き方をスッキリさせる

propsは、上記の通りオブジェクトなので、分割代入を使い、以下のようにpropsの記述を省略することができる。

const ColorfulMessage = (props) => {
  const { color, children } = props;
  const cotentStyle = {
    color: color,
    fontSize: "18px"
  };
  return (
    <>
      <p style={cotentStyle}>{children}</p>
    </>
  );
};

Stateを知る

stateを使う場合、reactのuseStateという関数を使用する。

そしてこのuseStateの中から、変数を、配列の分割代入で取り出し、 設定していく 。

配列に定義するのは、stateを使用するための変数名と、更新するための関数名

  const [num, setNum] = useState(0);

useStateの( )の中で初期値を設定できる。

const App = () => {
  const onClickCountUp = () => {
    setNum(num + 1);
  };
  const [num, setNum] = useState(0);

  return (
    <>
      <button onClick={onClickCountUp}>カウントアップ</button>
      <p>{num}</p>
    </>
  );
};

これでボタンがクリックされるとnumが0から+1ずつカウントアップされる。

再レンダリング

ボタンクリックで表示/非表示を切り替える

書き方のコツ

コンポーネント内で使うstateの記述は、定義コンポーネントの直下に記述すると見やすくなる。

論理演算子を使いBooleanで表示条件を設定する。

{showText && <p>表示されたよ!</p>}

左の要素がtrueのときに右を返す。falseのときに左を返す。

const App = () => {
  const [showText, setShowText] = useState(true);

  const onClickShowText = () => {
    setShowText(!showText);              ←これによりshowTextが持っているBoolean値の反対に切り替わる
  };

  return (
    <>
      <button onClick={onClickShowText}>on/off</button>
      {showText && <p>表示されたよ!</p>}
    </>
  );
};

上記で作った表示/非表示を3の倍数でのみ表示されるようにする

条件式の書き方NG例

  if (num % 3 === 0) {
    setShowText(true);
  } else {
    setShowText(false);
  }

このようにstateの更新をミスると以下のようなエラーとなるため注意が必要

Too many re-renders. React limits the number of renders to prevent an infinite loop.

なぜ大量の再レンダリングが起きてしまっているのか?

stateが変更されると、処理が先頭に戻り、また上記の条件文に戻ってきた時に同じ処理を繰り返す。

そうならないためにどうすれば良いか。

stateがtrueのとき、falseのときという条件を追加し以下のようにする。

  if (num % 3 === 0) {
    showText || setShowText(true);
  } else {
    showText && setShowText(false);
  }

もう一つ問題がある!

扱う変数が多くなると、 変数が互いに邪魔しあい、片一方の変数が効かなくなってしまう。

そこで”関心の分離”をする。

使用するのがuseEffect

useEffect

useEffrctの使い方

  useEffect(() => {
    if (num % 3 === 0) {
      showText || setShowText(true);
    } else {
      showText && setShowText(false);
    }
  }, [num]);

useEffectの第二引数に配列を取る。

最初の一回だけ通したいような処理を実行する場合は、配列を空配列[ ] とする。

今回の場合、このifの条件式はnumの変数のみで有効としたいため、配列にはnumを記述する。

このnumはカウント数であり、こう記述することによってon/off(showText)に影響を与えないようになる。

上記のような記述をすると、 eslint の警告文(エラーっぽういもの)が表示される。

eslintとは、useEffectの中で使っている変数は、全て第2引数の[ ]の中で書かないと、バグになる可能性があるという意味。

exportの2パターン

defaultを使う場合
export default ColorfulMessage;

import側

import ColorfulMessage from "./components/ColorfulMessage";

ちなみに…ここでのColorfulMessageという名称はこのファイル内で任意に付けた名称

defaultではない通常のexport

関数コンポーネントの前にexportを付ける

export const ColorfulMessage = (props) => {

この場合のimportは分割代入する必要がある。

import { ColorfulMessage } from "./components/ColorfulMessage";

それに対しこの名称は読み込みファイルのコンポーネントの名称

そのため、 defaultではない通常のexport による記述とすることで、typoがあったときにエラーとなり気づくのでこちらを使用するのがおすすめ!

コメント

タイトルとURLをコピーしました