JSX記法
まずReactでは、JSX記法
と呼ばれる書き方を使用します。これは、JavaScript XMLの略であり、JavaScriptのファイルの中でHTMLのようなタグを記述できるというもので、JavaScriptの拡張構文です。
import { createRoot } from 'react-dom/client';
import { App } from './App';
const container = document.getElementById('app');
const root = createRoot(container!);
root.render(<App />);
引数が<App />
となっていますがReactでは関数名をHTMLのようにタグで囲むことによってコンポーネント
として扱うことができます。
TypeScriptを使う場合は、警告が出るのでconst root = createRoot(container!);
の部分では!
を忘れずにつけましょう。
getElementById('app')
のappが何を示しているかというとHTMLのdivタグを示しています。
<!DOCTYPE html>
<html lang="en">
<head>
省略
</head>
<body>
<div id="app"></div> // 指示されたdivタグ
</body>
</html>
SPAの場合,HTMLファイルは1つのみ
なのでこのようにHTMLのここにコンポーネントをレンダリングする形で指定してあげます。
例として、Appコンポーネントの中身が下記だとします。
export const App = () => {
return (
<>
<h1>Hello.World</h1>
<p>はじめまして</p>
</>
);
};
ブラウザで確認してみると、Appが出力されていると思います。このようにJSX記法では、関数の返却値としてHTMLのタグが記述でき、それをコンポーネントとして扱って画面を構成していきます。
JSXのルール
先ほどのApp関数を例にします。まずreturn
以降が複数行になる場合は( )
で囲ってあげます。
そしてもう1つreturn以降は1つのタグで囲われている必要がある
というものです。今回は空タグを使って囲っています。divタグなどでも問題ないですが、空タグの場合は、不要なDOMは生成されないのでエラーを回避する有効な手段になります。
コンポーネント
React開発では、画面の要素を様々なコンポーネントに分割することで、再利用性や保守性を高めるのが基本になります。
先ほど作成したApp関数などのように関数で定義されたコンポーネントを関数コンポーネント
と言います。
export const App = () => {
return (
<>
<h1>Hello.World</h1>
<p>はじめまして</p>
</>
);
};
関数コンポーネントは、他のファイルでも使えるようにexport
する必要があります。exportされたものはimport
することで他のファイルでも使用することができます。
最初のコードを例にすると
import { createRoot } from 'react-dom/client';
import { App } from './App';
const container = document.getElementById('app');
const root = createRoot(container!);
root.render(<App />);
同階層にあるApp.jsからAppという名前の関数コンポーネントを読み込んでいるのがわかります。拡張子は省略可能です。
このように各ファイルでコンポーネントを定義しておいて、他のファイルから読み込んで画面を構成していくのがReactです。
ファイルの拡張子
Reactは、JavaScriptが動いているだけなので、.js
という拡張子で動作させることができます。コンポーネントの場合は.jsx
という拡張子でも動作します。TypeScriptの場合は、.tsx
です。
エディタの設定にもよりますが拡張子を変えることで、ファイルのアイコンも変わってくれるので便利です。
イベントやスタイルの扱いについて
まずはイベントの扱い方として、ボタンを押すとalertを実行する機能を作成してみます。
export const App = () => {
const clickButton = () => {
alert();
};
return <button onClick={clickButton}>ボタン</button>
};
これでボタンを押すとalertが表示されます。Reactではイベント等はキャメルケース
にします。キャメルケースとは、単語の繋ぎ部分は大文字にする記法です。そしてもう1つ、JSX記法ではタグの中では{ }
で囲むことでJavaScriptを記述することができます。
次に、スタイルの扱い方です。通常のHTML同様、Reactでもstyle
属性を使用してスタイルを適用することができます。注意点として、CSSの要素はJavaScriptのオブジェクト
として記述します。
export const App = () => {
return <h1 style={{ color: "red" }}>Hello.World</h1>
};
styleを指定しJavaScriptを書くので、{ }で囲み、その中にオブジェクトでCSSに対応する要素を指定するので{{ }}となっています。
Props
Propsは、コンポーネントに渡す引数のようなものです。コンポーネントは、受け取ったPropsに応じて表示するスタイルや内容を変化させます。例としてコードにピンク色の文字を追加してみます。
export const App = () => {
const pinkStyle = {
color: "Pink",
fontSize: "10px"
};
return <h1 style={pinkStyle}>Hello.World</h1>
};
上記のようにすれば、実現することはできますが、似たようなstyleを書くのは面倒なので色とテキストをProps
として受け取って色付きの文字を返すコンポーネントを作成してみます。新たに、Coloredという関数を定義します。
export const Colored = () => {
const pinkStyle = {
color: "Pink",
fontsize: "10px"
};
return <h1 style={pinkStyle}>Hello.World</h1>
};
App内でColoredコンポーネントを使用してみます。
export const App = () => {
return <colored />;
};
これで先ほどと画面の表示は変わらず、文字の部分はコンポーネント化したものを表示できています。次は、Props
を使って動的に変更できるようにします。
Props
を使うためには、Propsを渡す方のコンポーネントと渡される方のコンポーネントの両方を修正する必要があります。
まず、渡す方はコンポーネントの中に任意で名称をつけて
Propsを渡します。そして=
のあとに実際に渡す値を設定します。
// colorとmessageをPropsとして渡す
export const App = () => {
return <colored color="Pink" message="Hello.World" />;
};
次に、渡された方でPropsを確認してみます。コンポーネントにはPropsがオブジェクト
として渡されてくるので任意の名称で受け取ります。(Propsという名称が多い)
// オブジェクトとして受け取る
export const Colored = (props) => {
const pinkStyle = {
color: props.color,
fontsize: "10px"
};
return <h1 style={pinkStyle}>{props.message}</h1>
};
styleのcolorの部分とmessageの部分はPropsで受け取ったものに変更しています。これで動的に色と文字を変更できるコンポーネントを作成することができました。
children
Propsにはこれまで任意の名称を設定していました。コンポーネントもHTMLのタグのように任意の要素を囲って使用することができます。そして、この囲まれた部分がchildren
としてPropsに渡されます。
// childrenとして渡す
export const App = () => {
return <Colored color="Pink">Hello.world</Colored>;
};
// childrenを受け取る
export const Colored = (props) => {
const pinkStyle = {
color: props.color,
fontsize: "10px"
};
return <h1 style={pinkStyle}>{props.children}</h1>
};
これで、テキスト部分に関してはchildrenを使用することができました。
以上が基本的なPropsとchildrenの使い方ですが、上記の例ではさらに分割代入
やオブシェクトの省略記法
を使ってもっと簡潔に記述することができます。
Coloredを見てみると、Propsを使う場合、毎回props.~と記述しています。この程度なら問題はないですが、Propsの数が多かったり何回も使用するときは少し面倒です。そこで最初にPropsを分割代入
しておきます。
export const Colored = (props) => {
const {color, children} = props;
const pinkStyle = {
color: color,
fontsize: "10px"
};
return <h1 style={pinkStyle}>{children}</h1>
};
分割代入をすることによって、記述を短くすることができました。さらに、colorはプロパティ名と設定値が同じになったのでオブジェクトの省略記法
を使うことができます。
export const Colored = (props) => {
const {color, children} = props;
const pinkStyle = {
color,
fontsize: "10px"
};
return <h1 style={pinkStyle}>{children}</h1>
};
State(useState)
Reactでは画面に表示するデータや、可変の状態は全てState
として管理します。コンポーネントの状態を表す値です。
イベント実行時等に更新処理を行うことで動的アプリケーションを実現していきます。
React Hooks
という機能群の中のuseState
という関数を使ってStateを扱っていきます。useStateはReactに用意されているので使用する場合は以下のようにimportする必要があります。
// useStateのimport
import { useState } from "react";
そしてuseStateの返却値は配列の形で、1つ目に状態を持ったState変数
、2つ目にそのStateを更新する関数
が設定されます。
// useStateの使用例
const [count, setCount] = useState();
上記の場合count
が状態を持った変数、setCount
がそれを更新する関数になります。配列の分割代入と同じで名称は自由につけることができますが、暗黙のルールとして変数名にset変数名とします。そして、上記の場合、countにはまだ値が入っていないので初期値を設定したいケースはよくあります。その場合は、useStateに引数を設定します。
// State初期値の設定方法
const [count, setCount] = useState(0);
上記のように引数を与えることで、それがStateの初期値として設定されます。
では、例としてボタンを押した時にカウントアップする機能
を実装してみます。
import { useState } from "react";
export const App = () => {
//State定義
const [count, setCount] = useState(0);
// Stateをカウントアップする関数
const countButton = () => {
setCount(count + 1);
};
return (
<>
<button onClick={countButton}>ボタン</button>
<p>{count}</p>
</>
);
};
これでボタンを押すとsetCountでStateが更新されて値がカウントアップされていくはずです。
非常に簡単な使い方ですが、Stateの扱いとしてはこれだけです。ちなみに今回の数値だけではなく、オブジェクトや配列など何でもStateとして管理することができます。