【React】基本

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

この講座はほんとにいいです!これまで何をやってもReactを全然理解できなかった中、辿り着いたこちらの講座に本当に救われました。

【教育・学習】資格・学習
総合情報サイト「コレダ!」がお届けする教育・学習における資格・学習の総合情報サイトです。

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

Reactの基盤を作成

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

import React from 'react';

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

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

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

React17のアップデート ???

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

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

Introducing the New JSX Transform – React Blog
This blog site has been archived. Go to react.dev/blog to see the recent posts. Although React 17 doesn’t contain new features, it will provide support for a ne...

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

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

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

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

それでは、Reactの基盤作りに戻りましょう。

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

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つのタグで囲わないといけないというルールがあるからです。

そのため、2つの要素を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とは、コンポーネントに渡す引数的なもののこと。

propsの実用例を見てみます。

ColorfulMessageというコンポーネントを作成し、引数propsを定義します。

App.jsxのJSX内でColorfulMessageの値を定義し、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;

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.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のときに左辺を返す。

参考: ||を使う方法

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

左辺がfalseのとき右辺を返す。trueのとき左辺を返す。

参考: よく似たもので??を使う方法

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

左辺が undefined または null のときに右辺を返す。

つまり、??と||は同じ働きをする。

それでは実際に論理演算子を使ってみましょう!

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パターン

export にはdefaultとそうでないものの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のimportにに対し、この名称は読み込みファイルのコンポーネントの名称です。

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

以上、基本についてまとめました!

ご覧いただきありがとうございました。

コメント