Udemyのこちらの学習教材を通して学んだ、Reactの基礎をまとめました!
この講座はほんとにいいです!これまで何をやってもReactを全然理解できなかった中、辿り着いたこちらの講座に本当に救われました。
以前にも、基礎については以下にまとめていますので、こちらに重複する部分は割愛しています。
Reactの基盤を作成
まずは基盤を作成します。
import React from 'react';
reactって2つ書いてあるけど??
これの意味は、reactというライブラリから、Reactを読み込むという意味
React17のアップデート ???
Reactのアップデート情報はどこから取得すればよいのか?
ここに記載されていました!
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ずつカウントアップされる。
再レンダリング
ボタンクリックで表示/非表示を切り替える
論理演算子を使い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があったときにエラーとなり気づくことができるのでこちらを使用するのがおすすめ!
以上、基本についてまとめました!
ご覧いただきありがとうございました。
コメント