前置き
ご覧いただきありがとうございます。
Web制作会社で主にHTML・CSS・JavaScriptを書いているマークアップコーダーです。
モダンなフロントエンド技術を身に着けたく、今回は「React」についてざっくり学んでみました。
※注
基礎もまだまだの状況ですが、とりあえず「こんな感じなんだ〜」的なことを本当にざっくり書くだけです。
誰かのためになるわけでもわかりやすいわけでもない記事です。
Reactってなんだ?
今回は「React」です。
知る前のイメージ
「フロントエンドと言えばReactやVueでしょ!」的なイメージはあったが、
具体的にどんなものかイマイチわかっておらず。
JavaScriptのライブラリということで、jQueryみたいにhtmlファイルにReactを読み込んで書いて行くのかな?とかなんとか思っていました。
実態
別世界過ぎる。
直にHTML、CSS、JavaScriptを書いて静的ページ作っている自分にとっては、
node.jsで立ち上げる系のやつはほんとに違う世界。
htmlファイルに読み込むんじゃなくて、JavaScriptにHTMLを書くってか。
でもこのおかげでHTML(DOM)の操作がべらぼうにやりやすく柔軟に書いていける。
vanillaで書くより記述量が少なくわかりやすいと思いました。
Udemyのじゃけぇさんの講座で学びました。
機能と感想
JSX
「JavaScriptにHTMLを書くってか」と言いましたが、Reactでは「.js」または「.jsx」の拡張子のファイルに、JavaScriptとHTMLをどちらも記述します。
JSXはJavaScript XML の略らしいです。
※後に記載する「コンポーネント」ファイルを読み込む時に、エクスポートした関数名をそのままタグとして使用する、から?
「JavaScriptにHTMLを書くってか」(もういい)ですが、具体的には、
「JavaScriptの関数の中で、HTML構文をrerunで返す」という書き方になります。
const App = () => {
return (
<div className="App">
<p>JavaScriptにHTMLを書くってか!</p>
</div>
);
}
Reactでは、class ではなく className となります(JavaScriptのClassと分けるため)
コンポーネント
静的サイト制作でも使いまわしする共通パーツがありますが、大抵共通クラスを作って、そのクラスを指定してスタイルを合わせて、HTMLは都度書くような感じでした。
※JavaScriptでインクルードしたりもできますが
そういった共通パーツを一つのコンポーネントファイルで作成し、
必要な時にそのコンポーネントを読み込む、というのが基本のやり方のようです。
また共通パーツ以外にも、ひとまとまりの機能ごとでもコンポーネント化した方が、可読性や保守性も上がります。
なのでフォルダ数やファイル数は結構多くなる印象です。
で、コンポーネント化したものの「ここではちょっと変えて使いたい」とかはざらにありますが、
そういう時には「props」として値を渡すことで、使いたい場面ごとに一部を変えて使うということも可能です。
親(ページ)から子(コンポーネント)にpropsとして、例えばフォントカラーの値を渡すことで、親によって子のフォントカラーが変わるといった感じ。
import Child from "./components/Child";
const Parent = () => {
return (
<div className="Parent">
<Child color="red" />
</div>
);
}
export const Child = ({ props }) => {
return (
<p style={{color: props.color}}>JavaScriptにHTMLを書くってか!</p>
);
}
JSX内(return内)では、JavaScriptの構文は{}内に記述します。
レンダリング
レンダリングと言えばHTMLがブラウザに描画されることですが、Reactではそれが事あるごとに起きます(2回目以降のレンダリングを再レンダリングと呼ぶ)。
なので、ブラウザを更新しなくてもすぐに動的に反映できたりします。
※ただ意味もなく再レンダリングされるとモヤモヤするので(というかブラウザに負荷がかかるので)、必要のないときは再レンダリングされない手法もあります。このあたりちょっとややこしく感じたので慣れていきたいです。
スタイルの当て方
通常のHTMLと同様に、外部からCSSファイルを読みむということも可能ですが、
Reactでは色んな当て方があります。
Inline Styles
スタイルをオブジェクトで作成し、それをクラスに指定する方法。
オブジェクトで記載するのでプロパティはキャメルケースになります。
const container = {
backgroundColor: red,
}
export const Apps = () => {
return (
<div style={{ backgroundColor: 'red' }}></div> // 直接指定
<div style={container}></div> // 変数化して指定
);
}
CSS Modules
通常のCSSのように、外部ファイルを作成し、それをimportしてスタイルを当てる。
※ファイル名は「〇〇.module.css(またはscss)」
クラスの指定は、変数名.クラス名で指定。
import classes from '/CssModules.module.css'
export const Apps = () => {
return (
<div className={classes.container}></div> // CssModules.module.css内に container というクラスを作成
);
}
Styled JSX(CSS-in-JS)
外部ライブラリのため、npmなどでインストールして使用。
コンポーネント内に<style>
タグを記述し、タグ内にCSSを記述する。
<style jsx="true">{`
.container {
font-size: 16px;
}
`}</style>
export const Apps = () => {
return (
<div className="container"></div>
);
}
Styled Components
こちらも外部ライブラリのため、npmなどでインストールして使用。
スタイルを当てたコンポーネントを作成して変数に格納し、タグで囲む。
import styled from 'styled-components';
export const Apps = () => {
return (
<Container>
〜〜〜
</Container>
);
}
// divタグにスタイルを指定し、「Container」というコンポーネントを作成
const Container = styled.div`
background-color: red;
`;
他にも、「Tailwind」や「Emotion」などさまざまなライブラリがあるようで、
ちょっと覚えるのに苦労しそうだなという印象でした。
※一度に全部を覚える必要はないと思いますが、チームやプロジェクトによって使用するものが違うため、都度覚える必要があるかなと…
ルーティング・リンク
Reactでのルーティング(ページ遷移)は、react-router-dom
のRoutes
やRoute
、Link
などを使用します。かなりややこしい印象です。
リンクは、a
タグではなくLink
タグを使用します。
※遷移時も状態が維持されたり、速度が速いという理由?
遷移については、「ページ遷移する」というよりは「別のコンポーネントをレンダリングする」というイメージかなと思い、「このURLになるとこのコンポーネントをレンダリングする」という指示を書く必要があります。
具体的には、
Routes
の中にRoute
タグを記述し、path
とelement
でURLとそれに紐づくコンポーネントを指定します。
下記のコードでは、
PAGE1のリンクをクリックすると「〜/page1」のURLに変わり、Page1
コンポーネントが表示されます。
import { Routes, Route, Link } from "react-router-dom";
import Home from "./components/Home"; // トップページ(現在のコンポーネント)
import Page1 from "./components/Page1"; // 下層ページ
import Page2 from "./components/Page2"; // 下層ページ
export const App = () => {
return (
<div className="App">
<Link to="/">HOME</Link>
<Link to="page1">PAGE1</Link>
<Link to="page2">PAGE2</Link>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/page1" element={<Page1 />} />
<Route path="/page2" element={<Page2 />} />
</Routes>
</div>
);
}
state 状態管理
Reactでは状態管理が可能で、これによって動的な出力が容易に行えます。
例えば、ボタンをクリックしたらh1タグのテキストを変えるという実装の場合、
- h1タグのテキストを保持(変数に格納)
- ボタンをクリックすると1の変数の内容を変更(状態が更新される)
- 2で更新された変数をh1タグに挿入
といった具合です。
vanillaでも可能ですが、querySelector
やinnerText
でDOM取得などをする必要がありますが、
Reactでは「useState」という機能を使って容易にこの変更が可能です。
import { useState } from "react";
export const App = () => {
const [text, setText] = useState('最初のテキスト');
const onClickChange = () => {
setText('更新後のテキスト');
};
return (
<div className="App">
<h1>{text}</h1>
<button onClick={onClickChange}></button>
</div>
);
}
useStateは、分割代入で配列に状態を格納しますが、1つ目に状態の内容、2つ目に更新用関数が入ります(text
に内容、setText
に更新用関数)。
useState()の引数には初期値を指定し、更新用関数の引数に更新したい内容を指定するため、上記のコードでは、
textの初期値に「最初のテキスト」が入り、ボタンをクリックすることで「更新後のテキスト」に変更されます。
その内容をDOMに反映するには、{}内に変数を指定するだけで良いので、vanillaで書くよりずっと簡単に書けるな〜という印象です。
また、useStateを使用せずに、innerText
などで同様の処理を行った場合、
ボタンをクリックした再に再レンダリングが走り、再レンダリングされたことでtext
の中身も初期値に戻ってしまうため、こういった変更ではuseStateを使う必要があるということになります(useStateでは再レンダリング時も状態が保持される)。
まとめ
正直なところ、機能が多いのとややこしいと感じる箇所があり、まだまだ理解に及んでいませんが、とにかく動的な処理に関してすごく容易に書けるという印象を持ちました。
コンポーネント分割なども、書き方によって保守性が高まり、アプリやWebサービスではたしかに必須だということも納得しました。
今回はReactについてざっくり知りました。
Reactを使用したフレームワークのNext.jsにも興味があり、まだまだ学ぶことはたくさんありますが、徐々に身につけて行きたいと思っています。
読んでいただきありがとうございました!