完全に自分用です
ReactDOMによるレンダリング
Hello, ReactをReactコンポーネントで描画するベーシックなサンプルコード
index.html
<div id="root"></div>
<!-- コンポーネント表示場所の確保 -->
index.jsx
import { createRoot } from "react-dom/client"; //ReactDOM import
import React from "react"; //React import
import { App } from "./App.jsx"; //Appコンポーネント import
createRoot(
document.getElementById("root")
// idがrootのdiv要素を取得し、createRoot関数に渡す
).render(<App />); //Appコンポーネントのレンダリング
App.jsx
import React from "react";
export function App() {
return <div>Hello, React!</div>;
}
JSX
JSXはJS内でHTML記法が使えるJSの拡張. (上記App.jsx参照)
いくつか注意点あり.
-
inputやimgのような閉じタグがないタグも<img src="hoge.jpg"/>のようにスラッシュで閉じる - 複数のタグ(要素)があるときは、全てを一つの親要素でまとめる。
- JSの変数を
{}を使って埋め込める。- 例1:
<h1>Hello, {name}</h1> - 例2:
<a href={url}>リンク</a>
- 例1:
- 関数の戻り値がJSXで直接表示できる形であれば、関数をJSXで呼び出すこともできる。
- 例:
<h1>今は{getYear()}年です</h1>
- 例:
コンポーネントのimport & export
named export & import
import React from "react";
import { createRoot } from "react-dom/client";
import { Card } from "./card.jsx"; //card.jsxからCardコンポーネントをimport
//JSXでは<コンポーネント名 />でコンポーネントを呼び出す
export default function App() {
return <div className="container">
<Card />
</div>;
}
//レンダ
export const root = createRoot(document.getElementById("root"));
root.render(<App />);
export deafult & import
//export defalutでファイル内で一回だけ関数や変数、クラスを外部に公開できる
//今回は、function Card()がdefault exportされているとする
//export default→importのときは、{}を使わずに好きな名前でimport OK
import Card from "./card.jsx";
export default function App() {
return <div className="container">
<Card />
</div>;
}
公開ライブラリのimport
- まずライブラリをインストールする必要あり。
npmを使うことが多いnpm install ライブラリ名
- インストール後、import
import 変数名 from "ライブラリ名";
- ライブラリによってはnamed exportされているのでその場合は
{}を使ってimportimport {名前1, 名前2,} from "ライブラリ名";
JSから直接CSSを読み込む
- JSではビルドツールを使っていれば
importで書ける- 例:
import "./style.css";
- 例:
- 複数のコンポーネントが同じ CSS クラス名を使っている場合、衝突することに注意
Props
//コンポーネントに外からデータを渡すことができる.
//titleやtextの部分をPropsという
<Card
title="タイトル"
text="本文"
/>;
//Propsを受け取る側
//方法1:1つのオブジェクトとして受け取る
function Card(props) {
return (
<div className="card">
<h1 className="card-title">{props.title}</h1>
<p className="card-text">{props.text}</p>
</div>
);
}
//Propsを受け取る側
//方法2:JSの分割代入を使ってPropsから必要なデータだけ取り出す
function Card({ title, text }) {
return (
<div className="card">
<h1 className="card-title">{title}</h1>
<p className="card-text">{text}></p>
</div>
);
}
//あらかじめデフォルト値を設定しておくこともできる.
//titleが指定されずにCardコンポーネントが使われた場合、"タイトルなし"が表示される.
function Card({ title = "タイトルなし", text }) {
return (
<div className="card">
<h1 className="card-title">{title}</h1>
<p className="card-text">{text}></p>
</div>
);
}
children
コンポーネントのタグで挟んだ中身を受け取る特別なprops。
詳細:https://ja.react.dev/learn/passing-props-to-a-component#passing-jsx-as-children
// 使う側:タグで囲む
<Box>
<p>こんにちは</p> ←この部分がchildrenになる
</Box>
// 受け取る側:children として受け取って描画
function Box({ children }) {
return <div>{children}</div>;
}
コンポーネントへのstyleの適用
// style属性に二重中括弧{{ }}を使って、JSのオブジェクトを渡す
// オブジェクト内では、プロパティ名と値を:で区切る
<div style={{ color: "white" }}>
この文字が白くなる
</div>
このようなインラインstyleは基本的に避け、外部CSSが普通の書き方.
しかし、CSSの値を変数にして動的に表現したい場合などに使える.
いくつか注意.
- CSS プロパティ名がハイフンで区切られている場合は、camelCaseに変換する
- 例:
background-color→backgroundColor
- 例:
- 値はすべて文字列で指定する
- 例:
10px→"10px" - 例:
boxShadow: "0 6px 6px rgba(0, 0, 0, 0.2)" - ※単位が不要な
opacity : 0.5などはそのまま使える
- 例:
条件によって特定のコンポーネントを表示/非表示にする
// &&を使うと、条件がtrueの時だけコンポーネントや要素を表示する
{
条件 && <表示したいコンポーネント />;
}
// 三項演算子で書く
{
条件 ? <真の場合のコンポーネント/> : <偽の場合のコンポーネント/>;
}
ユーザがログインしているときだけ「ログイン済みです」を表示するコンポーネント
const isLoggedIn = true;
export function App() {
return (
<div>
{isLoggedIn && (
<p>ログイン済みです</p>
)}
</div>
);
}
// 条件を反転させるなら !isLoggdeIn
// propsでプロパティを受け取って同様の実装をすることもできる
import React from "react";
function LoginStatus(props) {
return (
<div>
{props.isLoggedIn && (
<p className="message-box info">
ログイン済みです
</p>
)}
{!props.isLoggedIn && (
<p className="message-box error">
ログインしていません
</p>
)}
</div>
);
}
export function App() {
return (
<div>
<LoginStatus isLoggedIn={true} />
<LoginStatus isLoggedIn={false} />
</div>
);
}
// isLoggedInプロパティにtrueを渡しているが、省略して<LoginStatus />としてもOK.
条件で表示/非表示(&& 演算子)
条件が true のときだけ要素を表示。逆条件は ! を組み合わせる。
{isLoggedIn && <p>ログイン済みです</p>}
{!isLoggedIn && <p>ログインしていません</p>}
Props で真偽値を渡すとき、true は省略可能。
<LoginStatus isLoggedIn /> {/* = isLoggedIn={true} */}
<LoginStatus isLoggedIn={false} />
三項演算子で表示切り替え
「真の場合 / 偽の場合」を一行で出し分けたいときに使う。
{isLoggedIn ? <p>ログイン済みです</p> : <p>ログインしていません</p>}
ネストすれば多分岐にもできる(深くしすぎ注意)。
{isLoggedIn
? userType === "admin" ? <p>管理者</p>
: userType === "member" ? <p>会員</p>
: <p>ゲスト</p>
: <p>未ログイン</p>}
条件でクラス名を変更
if 文で組み立てる
let className = "button";
if (props.role === "admin") className += " red";
else if (props.role === "user") className += " blue";
else className += " gray";
return <button className={className}>Click</button>;
clsx で簡潔に書く
オブジェクトのキーがクラス名、値が true のキーだけ適用される。
import clsx from "clsx";
const className = clsx({
red: props.role === "admin",
blue: props.role === "user",
gray: props.role !== "admin" && props.role !== "user",
});
第1引数に文字列を渡すと「無条件で常に付くクラス」になる。
const className = clsx("button", {
red: props.role === "admin",
blue: props.role === "user",
});
配列をリスト表示(map + key)
map で配列の各要素を JSX に変換。各要素には必ず一意な key を指定する。
const fruits = ["りんご", "バナナ", "みかん"];
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
ポイント:
-
keyは変更/追加/削除時に React が要素を識別するために使う - 一意な値を指定する(インデックス利用は順序変更で不具合の原因になり非推奨)
安全に表示する(オプショナルチェイニング ?.)
null / undefined のプロパティに直接アクセスするとエラーになる。?. を使えば安全に辿れる(途中が無ければ undefined を返す)。
{users.map((user) => (
<div key={user.id}>
<p>{user.name}</p>
<p>所在地:{user.address?.city}</p>
<p>郵便番号:{user.address?.postcode}</p>
</div>
))}
null / undefined の違い:
-
null… 「意図的に空」 -
undefined… 「まだ値が設定されていない」
データがないときの代替表示(Null 合体演算子 ??)
左辺が null / undefined のとき、右辺の値を返す。デフォルト値の指定に便利。
const result = data ?? "データが空っぽです";
?. と組み合わせると、安全アクセス+親切メッセージが両立できる。
<p>所在地:{user.address?.city ?? "所在地が登録されていません"}</p>
<p>郵便番号:{user.address?.postcode ?? "郵便番号が登録されていません"}</p>
注意:?? は null / undefined のときのみ右辺を返す(0 や "" は左辺がそのまま使われる)。
Fragment(余計な div を増やさない)
複数要素をまとめたいが、ラッパー要素を DOM に出したくないとき使う。
Fragment コンポーネント
import { Fragment } from "react";
function App() {
return (
<Fragment>
<h1>これは見出しです。</h1>
<p>これは本文です。</p>
</Fragment>
);
}
省略記法 <> </>(import 不要)
function App() {
return (
<>
<h1>これは見出しです。</h1>
<p>これは本文です。</p>
</>
);
}
key を指定する場合
省略記法 <> </> には key を渡せないので、Fragment タグを使う。
{items.map((item) => (
<Fragment key={item.term}>
<dt>{item.term}</dt>
<dd>{item.definition}</dd>
</Fragment>
))}
| x | y |
|---|---|
| 表示する/しない |
条件 && <Comp /> / !条件 && <Comp />
|
| AかBか出し分け | 条件 ? <A /> : <B /> |
| クラス名を条件で変える |
if/else または clsx({...})
|
| 配列をリスト化 | arr.map(x => <li key={…}>…</li>) |
| null安全にプロパティ参照 | obj?.prop |
| 値が無い時のデフォルト | value ?? "代替" |
| 余計なタグなしで複数要素を返す |
<>…</> / <Fragment>…</Fragment>
|