Reactコンポーネントのスタイルを設定する方法
著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
このチュートリアルでは、 React コンポーネントのスタイルを設定する3つの異なる方法を学習します。プレーンカスケードスタイルシート(CSS)、 JavaScriptスタイルオブジェクトを使用したインラインスタイル、 JSS 、JavaScriptでCSSを作成するためのライブラリ。 これらのオプションにはそれぞれ長所と短所があり、スタイルの競合に対する保護を強化したり、小道具やその他の動的データを直接参照したりできるものもあります。 ただし、すべてのオプションに共通する点が1つあります。これらのオプションを使用すると、コンポーネント固有のスタイルをコンポーネントに近づけて、プロジェクト全体または関連のない多くのプロジェクト間でコンポーネントを再利用しやすくなります。
これらの各オプションは、CSSプロパティに依存しています。 ランタイムデータなしでプレーンCSSを使用するには、スタイルシートをインポートできます。 コンポーネントと統合されたスタイルを作成する場合は、CSSプロパティ名をキーとして使用し、スタイルを値として使用するインラインスタイルオブジェクトを使用できます。 最後に、組み合わせが必要な場合は、JSSなどのサードパーティライブラリを使用して、JavaScript構文でCSSを記述できます。これは、CSS-in-JSと呼ばれるソフトウェアの概念です。
これらのメソッドを説明するために、propに応じて成功スタイルまたはエラースタイルのいずれかを表示するサンプルalertコンポーネントを作成します。 alertコンポーネントは、任意の数の子を取ります。 これは、子コンポーネントのスタイルを知る方法がないため、スタイルの競合に注意する必要があることを意味します。 alertコンポーネントを作成したら、各スタイリングオプションを使用してリファクタリングし、アプローチ間の類似点と相違点を確認できるようにします。
前提条件
- Node.jsを実行する開発環境が必要になります。 このチュートリアルは、Node.jsバージョン10.20.1およびnpmバージョン6.14.4でテストされました。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはのPPAを使用したインストール]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。
- Create ReactAppでアプリを作成できる必要があります。 Create React Appを使用してアプリケーションをインストールする手順については、 Create ReactAppを使用してReactプロジェクトをセットアップする方法を参照してください。
- Reactコンポーネントを使用します。これについては、Reactチュートリアルでカスタムコンポーネントを作成する方法で学ぶことができます。
- また、 JavaScriptでコーディングする方法シリーズにあるJavaScriptの基本的な知識と、HTMLおよびCSSの基本的な知識も必要です。 HTMLとCSSの優れたリソースは、 Mozilla DeveloperNetworkです。
ステップ1—空のプロジェクトを作成する
このステップでは、 Create ReactAppを使用して新しいプロジェクトを作成します。 次に、プロジェクトをブートストラップするときにインストールされるサンプルプロジェクトと関連ファイルを削除します。 最後に、コンポーネントを整理するための単純なファイル構造を作成します。 これにより、次のステップでスタイリングするためのこのチュートリアルのサンプルアプリケーションを構築するための確固たる基盤が得られます。
まず、新しいプロジェクトを作成します。 ターミナルで次のスクリプトを実行し、create-react-appを使用して新しいプロジェクトをインストールします。
npx create-react-app styling-tutorial
プロジェクトが終了したら、次のディレクトリに移動します。
cd styling-tutorial
新しいターミナルタブまたはウィンドウで、 CreateReactApp開始スクリプトを使用してプロジェクトを開始します。 ブラウザは変更時に自動更新されるため、作業中はこのスクリプトを実行したままにします。
npm start
実行中のローカルサーバーを取得します。 プロジェクトがブラウザウィンドウで開かなかった場合は、 http:// localhost:3000/でプロジェクトを開くことができます。 これをリモートサーバーから実行している場合、アドレスはhttp://your_domain:3000になります。
ブラウザには、CreateReactAppの一部として含まれている単純なReactアプリケーションが読み込まれます。
完全に新しいカスタムコンポーネントのセットを構築するので、空のプロジェクトを作成できるように、ボイラープレートコードをクリアすることから始める必要があります。
まず、テキストエディタでsrc/App.jsを開きます。 これは、ページに挿入されるルートコンポーネントです。 すべてのコンポーネントはここから始まります。 App.jsの詳細については、 Create ReactAppを使用してReactプロジェクトをセットアップする方法を参照してください。
次のコマンドでsrc/App.jsを開きます。
nano src/App.js
次のようなファイルが表示されます。
スタイリング-tutorial/src / App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
import logo from './logo.svg';の行を削除します。 次に、returnステートメントのすべてを置き換えて、空のタグのセット<></>を返します。 これにより、何も返さない有効なページが表示されます。 最終的なコードは次のようになります。
スタイリング-tutorial/src / App.js
import React from 'react';
import './App.css';
function App() {
return <></>;
}
export default App;
テキストエディタを保存して終了します。
最後に、ロゴを削除します。 アプリケーションで使用することはないので、作業中に未使用のファイルを削除する必要があります。 長期的には混乱からあなたを救うでしょう。
ターミナルウィンドウで、次のコマンドを入力します。
rm src/logo.svg
ブラウザを見ると、空白の画面が表示されます。
サンプルのCreateReactAppプロジェクトをクリアしたので、単純なファイル構造を作成します。 これにより、コンポーネントを分離して独立させることができます。
srcディレクトリにcomponentsというディレクトリを作成します。 これにより、すべてのカスタムコンポーネントが保持されます。
mkdir src/components
各コンポーネントには、スタイル、画像、テストとともにコンポーネントファイルを保存するための独自のディレクトリがあります。
Appのディレクトリを作成します。
mkdir src/components/App
すべてのAppファイルをそのディレクトリに移動します。 ワイルドカード*を使用して、ファイル拡張子に関係なく、App.で始まるファイルを選択します。 次に、mvコマンドを使用して、それらを新しいディレクトリに配置します。
mv src/App.* src/components/App
次に、index.jsの相対インポートパスを更新します。これは、プロセス全体をブートストラップするルートコンポーネントです。
nano src/index.js
importステートメントは、AppディレクトリのApp.jsファイルを指す必要があるため、次の強調表示された変更を行います。
スタイリング-tutorial/src / index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
ファイルを保存して終了します。
プロジェクトが設定されたので、最初のコンポーネントを作成できます。
ステップ2—プレーンCSSを使用したコンポーネントのスタイリング
このステップでは、Webページにアラートを表示するサンプルAlertコンポーネントを作成します。 コンポーネントに直接インポートするプレーンCSSを使用してこれをスタイル設定します。 これにより、コンポーネントのスタイルがコンポーネントのJavaScriptおよびJSXと緊密に結合されたままになります。 また、Alertコンポーネントを実装するコンポーネントを作成して、スタイルが子にどのように影響するか、および小道具を使用してスタイルを動的に変更する方法を確認します。
このステップの終わりまでに、コンポーネントに直接インポートされたプレーンCSSを使用するいくつかのコンポーネントが作成されます。
アラートコンポーネントの構築
まず、新しいAlertコンポーネントを作成します。 まず、ディレクトリを作成します。
mkdir src/components/Alert
次に、Alert.jsを開きます。
nano src/components/Alert/Alert.js
文字列Alertを返す基本コンポーネントを追加します。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
export default function Alert() {
return <div>Alert</div>
}
ファイルを保存して閉じます。
次に、App.jsを開きます。
nano src/components/App/App.js
Alertコンポーネントをインポートし、強調表示されたコードを追加して<div>内にレンダリングします。
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import './App.css';
import Alert from '../Alert/Alert';
function App() {
return (
<div className="wrapper">
<Alert />
</div>
)
}
export default App;
このコードでは、<div>にwrapperのclassNameを指定しました。これは、後でスタイリングに使用されます。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、コンポーネントが表示されます。
次に、Appコンポーネントのスタイルを設定して、Alertコンポーネントがエッジにあまり近づかないようにパディングを加えます。 App.cssファイルを開きます。
nano src/components/App/App.css
このファイルは標準のCSSを使用しています。 ラッパーにパディングを追加するには、プレーンHTMLプロジェクトのCSSの場合と同様に、デフォルトのコードをルールに置き換えます。 この場合、20pxのpaddingを追加します。
スタイリング-チュートリアル/src/components/App/App.css
.wrapper {
padding: 20px;
}
ファイルを保存して閉じます。 これを行うと、ページが更新され、追加のパディングが表示されます。
Create React Appを使用すると、 webpack はインポートされたCSSを取得し、ブラウザーでレンダリングされたファイルの上部にあるスタイルタグに追加します。 ページソースの<head>要素を見ると、次のスタイルが表示されます。
これは、CSSをコンポーネントと一緒に保持でき、ビルドフェーズ中に一緒に収集されることを意味します。 また、スタイルの範囲がグローバルであるため、名前の競合が発生する可能性があります。 このメソッドでは、各クラス名はすべてのコンポーネントで一意である必要があります。
この問題を調査するには、Alertコンポーネントにいくつかの変更を加えます。
まず、ファイルを開きます。
nano src/components/Alert/Alert.js
次に、children、type、およびtitleを小道具として使用するReactコードを追加します。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
import PropTypes from 'prop-types';
export default function Alert({ children, title, type }) {
return (
<div>
<h2>{title}</h2>
{children}
</div>
)
}
Alert.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element.isRequired
]),
title: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
}
このコードのtitleは<h2>タグ内にあり、childrenを使用すると子コンポーネントを表示できます。 間もなくtypeプロップを使用して、PropTypesタイピングシステムに基づいて成功とエラーアラートを設定します。
ファイルを保存して閉じます。 次に、AppのAlertコンポーネントを更新して、新しい小道具を使用します。
まず、App.jsを開きます。
nano src/components/App/App.js
ショッピングカートにアイテムを追加しようとして失敗したことをユーザーに通知するアラートを作成します。
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import './App.css';
import Alert from '../Alert/Alert';
function App() {
return (
<div className="wrapper">
<Alert title="Items Not Added" type="error">
<div>Your items are out of stock.</div>
</Alert>
</div>
)
}
export default App;
このコードでは、titleとchildrenを失敗メッセージで更新してから、errorのtypeを追加しました。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、新しいコンポーネントが表示されます。
アラートはレンダリングされているので、次のステップはCSSでコンポーネントのスタイルを設定することです。
AlertコンポーネントへのCSSの追加
Alertコンポーネントはエラーを表示するため、境界線を追加し、境界線の色を赤の色合いに設定します。 <h2>タグにも同じ色を付けます。 ただし、これには問題があります。Alertコンポーネントの外側の<div>にwrapperという名前を使用することはできません。これは、その名前がすでに[によって使用されているためです。 X160X]コンポーネント。
クラス名の競合はCSSの新しい問題ではなく、BEMなどの命名規則を使用して解決するための多くの試みがありました。 ただし、命名規則は冗長になる可能性があり、それでも、多数のコンポーネントを含むプロジェクトで競合が発生する可能性があります。
このチュートリアルでは、命名規則で区切られた特定のルールセットを使用するのではなく、wrapperクラス名の前にコンポーネントの名前を付けます。 新しいクラス名はalert-wrapperになります。 さらに、アラートのtypeをクラスとして追加します。
Alertコンポーネントを開きます。
nano src/components/Alert/Alert.js
次に、次の強調表示されたコードを追加します。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
import PropTypes from 'prop-types';
import './Alert.css';
...
export default function Alert({ children, type, title }) {
return(
<div className={`alert-wrapper ${type}`}>
<h2>{title}</h2>
{children}
</div>
)
}
...
この場合、テンプレートリテラルを使用して、alert-wrapper変数とtype変数を1つの文字列に結合しています。
ファイルを保存して閉じます。 これで、小道具に基づいて動的に変化する一意のクラス名ができました。 このコードのJSXは、クラス名がalert-wrapperおよびerrorのdivに解決されます。 コンパイルされたマークアップは次のようになります:<div class="alert-wrapper error">。
次に、スタイルを追加します。 まず、AlertコンポーネントのCSSを開きます。
nano src/components/Alert/Alert.css
次のCSSをalert-wrapper、success、およびerrorクラスに追加します。
スタイリング-チュートリアル/src/components/Alert/Alert.css
.alert-wrapper {
padding: 15px;
margin-bottom: 15px;
}
.alert-wrapper h2 {
margin: 0 0 10px 0;
}
.alert-wrapper.success {
border: #6DA06F solid 1px;
}
.success h2 {
color: #6DA06F;
}
.alert-wrapper.error {
border: #F56260 solid 1px;
}
.error h2 {
color: #F56260;
}
このコードは、alert-wrapperにいくつかのマージンとパディングを追加します。 次に、16進カラーコード#F56260と緑の色合い(#6DA06F)を使用して、errorクラスの赤の色合いの境界線を追加します。 successクラスの場合。 また、親に応じて<h2>の色を赤または緑に更新します。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、新しいスタイルが表示されます。
スタイル付きのAlertコンポーネントができたので、Alertコンポーネント内のアイテムのリストを表示する新しいコンポーネントを作成できます。 子供たちはより複雑になるので、スタイルの衝突の可能性が高くなります。
成功メッセージコンポーネントの作成
まず、新しいコンポーネントCartSuccessのディレクトリを作成します。
mkdir src/components/CartSuccess
CartSuccess.jsを開きます:
nano src/components/CartSuccess/CartSuccess.js
コンポーネント内で、Alertコンポーネントをインポートし、ユーザーがカートに追加した一連のアイテムを含む<div>を渡します。
スタイリング-tutorial/src / components / CartSuccess / CartSuccess.js
import React from 'react';
import Alert from '../Alert/Alert';
import './CartSuccess.css';
export default function CartSuccess() {
return(
<Alert title="Added to Cart" type="success">
<div className="cart-success-wrapper">
<h2>
You have added 3 items:
</h2>
<div className="item">
<div>Bananas</div>
<div>Quantity: 2</div>
</div>
<div className="item">
<div>Lettuce</div>
<div>Quantity: 1</div>
</div>
</div>
</Alert>
)
}
外側の<div>に一意のクラス名(cart-success-wrapper)を作成する必要があることに注意してください。 ファイルを保存して閉じます。
次に、CSSをカスタムメッセージに追加します。 CartSuccess.cssを開きます:
nano src/components/CartSuccess/CartSuccess.css
flexのdisplayをラッパーに追加します。 <h2>要素は、幅全体を占める必要があります。
スタイリング-チュートリアル/src/components/CartSuccess/CartSuccess.css
.cart-success-wrapper {
border-top: black solid 1px;
display: flex;
flex-wrap: wrap;
}
.cart-success-wrapper h2 {
width: 100%;
}
.item {
margin-right: 20px;
}
ここでは、<h2>に100%の幅を指定しました。 要素を変更することに加えて、メッセージの上部に小さな境界線を追加し、itemクラスにマージンを追加して、アイテム間にスペースを提供しました。
ファイルを保存して閉じます。
スタイル付きコンポーネントができたので、それをAppコンポーネントに追加します。
App.jsを開きます:
nano src/components/App/App.js
強調表示されたコードに示すように、コンポーネントをインポートし、現在のAlertコンポーネントの後に追加します。
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import './App.css';
import Alert from '../Alert/Alert';
import CartSuccess from '../CartSuccess/CartSuccess';
function App() {
return(
<div className="wrapper">
<Alert title="Items Not Added" type="error">
<div>Your items are out of stock.</div>
</Alert>
<CartSuccess />
</div>
)
}
export default App;
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、新しいコンポーネントが表示されます。
これにより、意図したとおりに新しい色とメッセージが表示されますが、ネストされたコンポーネントは予期しないスタイルを受け取りました。 Alertコンポーネントの<h2>のルールは、children小道具のネストされた<h2>タグに適用されます。
予期しないスタイルが子にカスケードされることは、CSSの一般的な問題です。 ただし、Reactを使用すると、プロジェクト間でコンポーネントをバンドルして共有する機会が得られるため、スタイルが誤って子コンポーネントに流れ落ちる可能性が高くなります。
純粋なCSSでこれを修正するには、Alertコンポーネントの<h2>ルールをもう少し具体的にします。
Alert.cssファイルを開きます。
nano src/components/Alert/Alert.css
<h2>スタイルが、CSS > 子コンビネーターを使用するすべての子ではなく、クラスの直接の子にのみ適用されるようにルールを変更します。
スタイリング-チュートリアル/src/components/Alert/Alert.css
.alert-wrapper {
padding: 15px;
margin-bottom: 15px;
}
.alert-wrapper > h2 {
margin: 0 0 10px 0;
}
.alert-wrapper.success {
border: #6da06f solid 1px;
}
.success > h2 {
color: #6da06f;
}
.alert-wrapper.error {
border: #f56260 solid 1px;
}
.error > h2 {
color: #f56260;
}
ファイルを保存して閉じます。 これを行うと、ページが更新され、CartSuccessの<h2>要素がデフォルトの色を保持していることがわかります。
これで、Alertコンポーネントのスタイルは直接の子にのみ影響し、他の子ノードまたはコンポーネントには適用されません。 この方法はこの場合はうまく機能しますが、コンポーネントがより複雑な状況では、コンポーネントの外部にリークせずにすべてのケースに適用されるルールを作成するのは難しい場合があります。
このステップでは、コンポーネントに直接インポートされたCSSスタイルシートを使用してコンポーネントのスタイルを設定しました。 標準のCSSを使用したReact要素のスタイリングは、標準のCSSファイルを使用して関連するスタイルのコンポーネントをすばやく作成する方法です。 使いやすさは、新しいプロジェクトや小さなプロジェクトに取り組んでいるときの最初のステップとしては良いものですが、プロジェクトが大きくなるにつれて問題が発生する可能性があります。
コンポーネントを構築するときに、2つの一般的なスタイルの問題が発生しました。クラス名の競合と意図しないスタイルの適用です。 これらは標準のCSSで回避できますが、命名規則ではなくプログラムでこれらの問題を処理するためのツールを提供する他のスタイル設定アプローチがあります。 次のステップでは、スタイルオブジェクトを使用してこれらの問題を解決する方法を検討します。
ステップ3—スタイルオブジェクトを使用したスタイリング
このステップでは、CSSプロパティをキーとして使用するJavaScriptオブジェクトであるスタイルオブジェクトを使用してコンポーネントのスタイルを設定します。 コンポーネントで作業するときは、JavaScript構文に一致するようにキーを更新し、コンポーネントの小道具に基づいてスタイルプロパティを動的に設定する方法を学習します。
個別のCSSは、HTMLのスタイルを設定する最も一般的な方法です。 この方法は高速であり、ブラウザーはスタイルを迅速かつ一貫して適用するのに効率的です。 ただし、HTMLのスタイルを設定するためのオプションはこれだけではありません。 標準のHTMLでは、 style属性を使用して、適用するスタイルを含む文字列を使用して、要素に直接インラインスタイルを設定できます。
スタイルオブジェクトの最適な使用法の1つは、スタイルを動的に計算することです。 これは、要素の現在の位置を知る必要がある場合に特に便利です。これは、要素がレンダリングされるまで決定されず、動的にしか処理できないためです。
スタイル文字列を手動で書くことは難しく、バグを引き起こす可能性があります。 色やセミコロンがない場合は、文字列全体が壊れます。 幸い、JSXでは、文字列だけに制限されていません。 style属性は、スタイルを含むオブジェクトを受け入れることもできます。 これらのスタイル名は、kebab-caseではなくcamelCaseである必要があります。
このようなインラインスタイルを使用する最大の利点は、JavaScriptを使用してスタイルを構築しているため、クラスを動的に設定する代わりに、CSSプロパティを動的に設定できることです。 これは、CSSクラスをまったく使用せずにコードを記述できることを意味し、潜在的な名前の競合を回避し、実行時にスタイルを計算できるようにします。
スタイルオブジェクトを使用するには、App.jsをリファクタリングすることから始めます。 まず、ファイルを開きます。
nano src/components/App/App.js
コンポーネント内で、インポートされたApp.cssファイルを削除し、paddingが20のオブジェクトを作成し、オブジェクトを<div>に渡します。 style属性:
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import Alert from '../Alert/Alert';
import CartSuccess from '../CartSuccess/CartSuccess';
function App() {
const wrapper = {
padding: 20
};
return(
<div style={wrapper}>
<Alert title="Items Not Added" type="error">
<div>Your items are out of stock.</div>
</Alert>
<CartSuccess />
</div>
)
}
export default App;
paddingの単位としてピクセルを指定する必要がないことに注意してください。 Reactはこれをデフォルトでピクセルの文字列に変換します。 特定のユニットが必要な場合は、それを文字列として渡します。 したがって、たとえばパディングをパーセンテージにする場合は、padding: '20%'になります。
ほとんどの数値は自動的にピクセルに変換されます。 ただし、例外があります。 プロパティline-heightは、単位なしのプレーンな数値を取ることができます。 その場合にピクセル単位を使用する場合は、ピクセルを文字列として指定する必要があります。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、以前と同じようにページが表示されます。
次に、CartSuccessをリファクタリングします。 まず、ファイルを開きます。
nano src/components/CartSuccess/CartSuccess.js
App.jsと同様に、インポートされたCSS(CartSuccess.css)を削除し、以前にクラスがあった各アイテムのスタイルオブジェクトを作成します。
スタイリング-tutorial/src / components / CartSuccess / CartSuccess.js
import React from 'react';
import Alert from '../Alert/Alert';
export default function CartSuccess() {
const styles = {
header: {
width: '100%'
},
item: {
marginRight: 20
},
wrapper: {
borderTop: 'black solid 1px',
display: 'flex',
flexWrap: 'wrap'
}
}
return(
<Alert title="Added to Cart" type="success">
<div style={styles.wrapper}>
<h2 style={styles.header}>
You have added 3 items:
</h2>
<div style={styles.item}>
<div>Bananas</div>
<div>Quantity: 2</div>
</div>
<div style={styles.item}>
<div>Lettuce</div>
<div>Quantity: 1</div>
</div>
</div>
</Alert>
)
}
この場合、複数の個別のオブジェクトを作成していません。 代わりに、他のオブジェクトを含む単一のオブジェクトを作成しました。 margin-right、border-top、およびflex-wrapのプロパティにはキャメルケースを使用する必要があることにも注意してください。
ファイルを保存して閉じます。 これを行うと、ページが更新され、同じスタイルのページが表示されます。
クラスを使用していないため、名前の競合について心配する必要はありません。 JavaScriptを使用してスタイルを作成するもう1つの利点は、変数やテンプレートリテラルなどのJavaScript構文を利用できることです。 最新のCSSでは、変数を使用できます。これは大幅な改善ですが、ブラウザーのサポート要件によっては完全に利用できない場合があります。 特に、 polyfill を使用してサポートを追加することはできますが、InternetExplorerのどのバージョンでもサポートされていません。
スタイルオブジェクトは実行時に作成されるため、より予測可能であり、サポートされている任意のJavaScriptを使用できます。
この状況でスタイルオブジェクトがどのように役立つかを確認するには、Alert.jsをリファクタリングしてスタイルオブジェクトを使用します。 まず、Alert.jsを開きます。
nano src/components/Alert/Alert.js
Alert.js内で、import './Alert.css';を削除し、エラー色のプロパティと成功色のプロパティを持つcolorsというオブジェクトを作成します。 次に、typeプロップを使用してCSSをJavaScriptオブジェクトに変換し、色を動的に設定します。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
import PropTypes from 'prop-types';
export default function Alert({ children, type, title }) {
const colors = {
success: '#6da06f',
error: '#f56260',
}
const style = {
heading: {
color: colors[type],
margin: '0 0 10px 0',
},
wrapper: {
border: `${colors[type]} solid 1px`,
marginBottom: 15,
padding: 15,
position: 'relative',
}
}
return(
<div style={style.wrapper}>
<h2 style={style.heading}>{title}</h2>
{children}
</div>
)
}
...
ここにいくつかの変更があります。 まず、wrapperに単一のスタイル宣言を使用してから、タイプに基づいて色を動的に設定します。 一般に<h2>要素をスタイリングしているのではなく、<h2>要素であるこれらの特定の要素をスタイリングしています。 要素タイプにスタイルを適用していないため、スタイルが子要素に流れ落ちる危険はありません。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、適用されたスタイルが表示されます。
スタイルオブジェクトは多くの問題を解決しますが、欠点があります。 まず、インラインスタイルのパフォーマンスコストがあります。 ブラウザはCSSを効率的に処理するように設計されており、インラインスタイルを適用するスタイルオブジェクトはこれらの最適化を利用できません。 もう1つの問題は、スタイルオブジェクトを使用して子要素にスタイルを適用することがより難しいことです。 この場合、スタイルを子に適用したくはありませんが、スタイルをカスケードしたい場合がよくあります。 たとえば、すべての要素にカスタムフォントファミリを設定したり、すべての<h2>要素にカスタムサイズを適用したりする場合は、あまり具体的でないスタイル戦略を使用すると簡単になります。
ただし、これらのアプローチの間には中間点があります。 いくつかのサードパーティライブラリは、この中間点を見つけるように設計されています。 次のステップでは、JSSと呼ばれるライブラリを使用してCSS-in-JSと呼ばれるハイブリッドアプローチを使用してスタイルを作成します。
ステップ4—JSSを使用したスタイリング
このステップでは、人気のあるライブラリJSSを使用してオブジェクトのスタイルを設定します。 新しいライブラリをインストールし、スタイルオブジェクトをJSSオブジェクトに変換します。 次に、コードをリファクタリングして、動的に生成されたクラス名を使用します。これにより、モジュール間でのクラス名の競合が防止されます。 また、スタイルを動的に設定し、ネストされたプロパティを使用して特定のスタイルルールを作成するJavaScriptスタイルオブジェクトを作成します。
JSSは、CSS-in-JSを作成するためのライブラリです。 この方法には多くのさまざまなユースケースとオプションがありますが、このチュートリアルの主な利点は、コンポーネント間の競合を回避する動的なクラス名を作成することです。 また、JavaScript構文を利用できるようになります。つまり、変数を使用して、Reactプロップに基づいてスタイルを作成できるようになります。
まず、React固有のバージョンのJSSをインストールします。 このチュートリアルでは、バージョン10.1.1を使用します。
npm install react-jss
このパッケージは、簡潔なスタイルのルールを記述できるようにする多数の JSSプラグインを含む、いくつかの依存関係をインストールします。
インストールが完了すると、成功メッセージが表示されます。
Output+ [email protected] added 281 packages from 178 contributors, removed 142 packages, updated 1392 packages and audited 1025251 packages in 144.872s
出力は、ノードのバージョンやその他の依存関係によってわずかに異なります。
ライブラリがインストールされたので、App.jsをJSSを使用するように変換します。 まず、App.jsを開きます。
nano src/components/App/App.js
JSSを使用するには2つのステップがあります。 まず、関数をインポートしてカスタムフックを作成する必要があります。 フックは、Reactがすべてのコンポーネントレンダリングで実行される関数です。 JSSでは、コンポーネントの外部でスタイル定義を渡してフックを作成する必要があります。 これにより、再レンダリングのたびにコードが実行されなくなります。 スタイル定義は静的であるため、コードを複数回実行する理由はありません。
強調表示された変更を行って、フックとスタイルオブジェクトを作成します。
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import { createUseStyles } from 'react-jss';
import Alert from '../Alert/Alert';
import CartSuccess from '../CartSuccess/CartSuccess';
const useStyles = createUseStyles({
wrapper: {
padding: 20,
}
});
function App() {
return(
<div>
<Alert title="Items Not Added" type="error">
<div>Your items are out of stock.</div>
</Alert>
<CartSuccess />
</div>
)
}
export default App;
この場合、スタイルオブジェクトにwrapperという別のオブジェクトが含まれていることに注意してください。このオブジェクトには、同じキャメルケース形式を使用するスタイルが含まれています。 オブジェクトの名前(wrapper)は、動的クラス名を作成するための基礎です。
フックを作成したら、コンポーネント内で関数を実行してフックを使用します。 これによりフックが登録され、スタイルが動的に作成されます。 次の強調表示された変更を行います。
スタイリング-チュートリアル/src/components/App/App.js
import React from 'react';
import { createUseStyles } from 'react-jss'
import Alert from '../Alert/Alert';
import CartSuccess from '../CartSuccess/CartSuccess';
const useStyles = createUseStyles({
wrapper: {
padding: 20,
}
});
function App() {
const classes = useStyles()
return(
<div className={classes.wrapper}>
<Alert title="Items Not Added" type="error">
<div>Your items are out of stock.</div>
</Alert>
<CartSuccess />
</div>
)
}
export default App;
このコードでは、関数を呼び出し、結果をclassesという変数に割り当てます。 新しい変数classesは、動的クラス名を含むオブジェクトになります。 次に、オブジェクトで定義したのと同じ名前を使用して、適切なクラス名を要素に適用します。 ここではclasses.wrapperを使用しました。
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、以前と同じスタイルが表示されます。 ただし、コンソールを見ると、クラス名がオブジェクトで定義したものと完全に一致していないことがわかります。
この場合、クラス名はwrapper-0-2-1ですが、クラス名が異なる場合があります。 また、スタイルがオブジェクトからCSSに変換され、<style>タグに配置されていることもわかります。 これを、CSSに変換されず、クラス名を持たないインラインスタイルと比較してください。
JSSはクラス名を動的に作成するため、他のファイルの同様の名前と競合することはありません。 これが機能することを確認するには、CartSuccess.jsをリファクタリングしてJSSスタイルを使用します。
ファイルを開きます。
nano src/components/CartSuccess/CartSuccess.js
ファイル内で、createUseStylesを使用してカスタムフックを作成します。 <h2>要素にクラスを適用する代わりに、ラッパー内に<h2>要素のルールを作成します。 プレーンCSSでこれを行うには、クラスと要素の間にスペースを追加します—.wrapper h2。 これにより、.wrapperクラスの子であるすべての<h2>要素にスタイルが適用されます。
JSSを使用すると、包含要素内に別のオブジェクトを作成することにより、同様のルールを作成できます。 それらをリンクするには、オブジェクト名を&記号で開始します。
スタイリング-tutorial/src / components / CartSuccess / CartSuccess.js
import React from 'react';
import { createUseStyles } from 'react-jss';
import Alert from '../Alert/Alert';
const useStyles = createUseStyles({
item: {
marginRight: 20
},
wrapper: {
borderTop: 'black solid 1px',
display: 'flex',
flexWrap: 'wrap',
'& h2': {
width: '100%'
}
}
})
export default function CartSuccess() {
const classes = useStyles();
return(
<Alert title="Added to Cart" type="success">
<div className={classes.wrapper}>
<h2>
You have added 3 items:
</h2>
<div className={classes.item}>
<div>Bananas</div>
<div>Quantity: 2</div>
</div>
<div className={classes.item}>
<div>Lettuce</div>
<div>Quantity: 1</div>
</div>
</div>
</Alert>
)
}
ラッパーのルールを作成することに加えて、itemのルールも作成しました。 カスタムフックを作成した後、カスタムクラス名をclassNameプロパティに渡しました。
ファイルを保存します。 このコンポーネントとAppコンポーネントの両方で同じ名前(wrapper)を使用していることに注意してください。 ただし、ブラウザがリロードされると、名前の競合は発生しません。 すべてが正しく見えます。 ブラウザで要素を調べると、同じ名前で始まっていても、それぞれに固有のクラスがあることがわかります。
この場合、外部コンポーネントのクラスはwrapper-0-2-1であり、Appコンポーネントで生成されました。 CartSuccessのクラスはwrapper-0-2-3です。 コンポーネント名は少し異なる場合がありますが、一意になります。
状況によっては、他のスタイルをオーバーライドするために特定のセレクターを作成する必要がある場合があります。 たとえば、要素がwrapperクラスの子である場合にのみ、itemスタイルを適用するとします。 これを行うには、最初にプロパティのないオブジェクトにクラスを作成します。 次に、wrapperクラス内で、$記号を使用して新しいクラスを参照します。
スタイリング-tutorial/src / components / CartSuccess / CartSuccess.js
import React from 'react';
import { createUseStyles } from 'react-jss'
import Alert from '../Alert/Alert';
const useStyles = createUseStyles({
item: {},
wrapper: {
borderTop: 'black solid 1px',
display: 'flex',
flexWrap: 'wrap',
'& h2': {
width: '100%'
},
'& $item': {
marginRight: 20
}
}
})
export default function CartSuccess() {
const classes = useStyles()
return(
<Alert title="Added to Cart" type="success">
<div className={classes.wrapper}>
<h2>
You have added 3 items:
</h2>
<div className={classes.item}>
<div>Bananas</div>
<div>Quantity: 2</div>
</div>
<div className={classes.item}>
<div>Lettuce</div>
<div>Quantity: 1</div>
</div>
</div>
</Alert>
)
}
ファイルを保存して閉じます。 ブラウザがリロードされると、ページは同じように見えますが、item CSSは、ラッパーコンポーネントの下のアイテムにより具体的に適用されます。
JSSを使用すると、通常のCSSで作成するのと同じレベルのフォーカスでルールを作成できますが、衝突しない一意のクラス名を作成しながら作成できます。
JSSの最後の利点の1つは、変数やその他のJavaScript言語機能を使用できることです。 react-jssを使用しているため、小道具をスタイルオブジェクトに渡して、動的なスタイルを作成できます。 これをテストするには、Alert.jsコンポーネントをリファクタリングして、小道具と変数を使用して動的プロパティを作成します。
まず、ファイルを開きます。
nano src/components/Alert/Alert.js
最後にリファクタリングされたコードで行ったように、スタイルオブジェクトを作成します。 createUseStyles関数と同じスコープにあるように、色を定義するオブジェクトをコンポーネント関数の外側に移動してください。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
import PropTypes from 'prop-types';
import { createUseStyles } from 'react-jss';
const colors = {
success: '#6da06f',
error: '#f56260',
};
const useStyles = createUseStyles({
wrapper: {
border: ({ type }) => `${colors[type]} solid 1px`,
marginBottom: 15,
padding: 15,
position: 'relative',
'& h2': {
color: ({ type }) => colors[type],
margin: [0, 0, 10, 0],
}
}
});
export default function Alert({ children, type, title }) {
const classes = useStyles({ type })
return(
<div className={classes.wrapper}>
<h2>{title}</h2>
{children}
</div>
)
}
...
小道具を渡すには、スタイルルールを関数にします。 この関数は、小道具を引数として受け入れ、ルールを返します。 動的な境界線を作成するには、プロパティ名としてborderを追加し、typeを受け取って文字列({ type }) => `${colors[type]} solid 1px`,を返す矢印関数を追加します。 次に、フックを作成した後、クラスオブジェクトを作成するときに参照する小道具を渡します。 以前と同様に、特定のクラスを作成する代わりに、要素ごとに<h2>タグのスタイルを設定します。 また、0px 0px 10px 10pxなどの文字列ではなく、marginの値の配列を渡します。
ファイルを保存します。 すべての小道具を関数に渡す必要はないことに注意してください。 この場合、typeのみを使用する必要があるため、合格する必要があるのはそれだけです。 ただし、残りの演算子を使用して小道具を収集し、それらをグループとして渡すことで、より多くの、または未知の小道具を渡すこともできます。 オブジェクトとして渡す必要があります。 ただし、これが小道具を渡すための標準的な方法であるため、将来的に引数を拡張しやすくなります。
ページがリロードされると、正しい色が表示されますが、わずかな問題があります。緑色の成功色がCartSuccessの<h2>要素を更新しています。
JSSは多くの問題を解決しますが、それでも標準のCSSを作成します。 つまり、注意しないと、スタイルが子要素に適用される可能性があります。 これを修正するには、>シンボルを追加して、CSSを直接の子にのみ適用するようにします。
スタイリング-チュートリアル/src/components/Alert/Alert.js
import React from 'react';
...
const useStyles = createUseStyles({
wrapper: {
border: ({ type }) => `${colors[type]} solid 1px`,
marginBottom: 15,
padding: 15,
position: 'relative',
'& > h2': {
color: ({ type }) => colors[type],
margin: [0, 0, 10, 0],
}
}
});
export default function Alert({ children, type, title }) {
...
}
...
ファイルを保存して閉じます。 これを行うと、ブラウザがリロードされ、正しいスタイルが表示されます。
JSSには、このチュートリアルで説明されている以上のことがたくさんあります。 まだ触れていない重要な利点の1つは、テーマです。 JSSを使用すると、事前定義されたテーマオブジェクトに基づいてスタイルを作成できます。 つまり、ハードコードされた値から赤の色を作成する代わりに、アラートの境界線をalertの色にすることができます。これは赤の色合いになる可能性がありますが、テーマの定義によって異なる場合があります。 これは、ホワイトラベル製品を作成する場合、またはプロジェクト間で機能する必要がある再利用可能なコンポーネントを作成する場合に役立ちます。
このステップでは、react-jssというサードパーティのライブラリを使用してコンポーネントのスタイルを設定しました。 また、スタイルオブジェクトを作成し、JSSを使用してそれらのオブジェクトを動的クラスに変換し、他のコンポーネントとの競合を回避しました。 このメソッドを使用すると、コードの後半で競合を心配することなく、単純なクラス名を安全に再利用できます。 最後に、関数と小道具を使用してスタイルを作成し、コンポーネントの小道具を参照する動的なスタイルを作成する方法を学びました。
結論
このチュートリアル全体を通して、さまざまなスタイルの手法を使用する再利用可能なコンポーネントをいくつか開発しました。 スタイルオブジェクトとJSSが、標準のCSSプロパティを厳密に反映する名前を使用してオブジェクトを作成する方法を学び、着信プロパティに基づいてスタイルを動的に設定できるコンポーネントを作成しました。 また、さまざまなアプローチが、名前の競合と再利用性を処理するためのさまざまなオプションをどのように提供するかについても学びました。
ほとんどのReactテクニックと同様に、単一の最良の解決策はありません。 代わりに、プロジェクトに最適なスタイリングオプションを選択できます。 これらのオプションを使用すると、プロジェクトの成長や要件の変更に応じて、シンプルなものから始めてリファクタリングすることができます。その一方で、コンポーネントが引き続きスタイルの目標を達成できることを確信できます。
Reactのチュートリアルをもっと見たい場合は、 Reactトピックページを確認するか、React.jsシリーズのコーディング方法ページに戻ってください。