برنامه نویسی

آموزش استایل‌دهی به کامپوننت‌های React

مقدمه

در این آموزش، سه روش مختلف برای استایل‌دهی به کامپوننت‌های React را یاد خواهید گرفت: استفاده از فایل‌های CSS ساده (Cascading Style Sheets)، استایل‌های درون‌خطی (Inline Styles) با استفاده از آبجکت‌های جاوااسکریپتی، و JSS (یک کتابخانه برای ساخت CSS با جاوااسکریپت). هر یک از این گزینه‌ها مزایا و معایب خود را دارد؛ برخی از آن‌ها محافظت بیشتری در برابر تداخل استایل‌ها به شما می‌دهند یا به شما اجازه می‌دهند مستقیماً به Props یا سایر داده‌های پویا (Dynamic) اشاره کنید. اما تمام این گزینه‌ها یک ویژگی مشترک دارند: به شما اجازه می‌دهند استایل‌های اختصاصی هر کامپوننت را در کنار همان کامپوننت نگه دارید، که این امر استفاده مجدد از کامپوننت‌ها را در یک پروژه یا حتی در پروژه‌های نامرتبط بسیار آسان‌تر می‌کند.

هر یک از این روش‌ها بر پایه ویژگی‌های (Properties) CSS استوار هستند. برای استفاده از CSS ساده بدون نیاز به داده‌های زمان اجرا (Runtime Data)، می‌توانید فایل‌های استایل را Import کنید. اگر می‌خواهید استایل‌هایی بسازید که با کامپوننت یکپارچه باشند، می‌توانید از آبجکت‌های استایل درون‌خطی استفاده کنید که در آن‌ها از نام ویژگی‌های CSS به عنوان کلید (Key) و از استایل به عنوان مقدار (Value) استفاده می‌شود. در نهایت، اگر به ترکیبی از این دو نیاز دارید، می‌توانید از یک کتابخانه شخص ثالث (Third-party) مانند JSS برای نوشتن CSS با سینتکس جاوااسکریپت استفاده کنید که به این مفهوم نرم‌افزاری CSS-in-JS گفته می‌شود.

برای نمایش این روش‌ها، یک کامپوننت Alert (هشدار) نمونه می‌سازید که بسته به Prop دریافتی، либо استایل موفقیت (Success) یا استایل خطا (Error) را نشان دهد. این کامپوننت می‌تواند هر تعداد کامپوننت فرزند (Children) را دریافت کند. این بدان معناست که باید در مورد تداخل استایل‌ها محتاط باشید، زیرا راهی برای دانستن استایل‌های کامپوننت‌های فرزند ندارید. پس از ساخت کامپوننت Alert، با استفاده از هر یک از گزینه‌های استایل‌دهی آن را بازنویسی (Refactor) می‌کنید تا شباهت‌ها و تفاوت‌های بین این رویکردها را مشاهده کنید.

پیش‌نیازها

برای انجام این آموزش به یک محیط توسعه که Node.js روی آن اجرا می‌شود نیاز دارید. این آموزش با Node.js نسخه 20.x.x و npm تست شده است. برای نصب آن روی سیستم‌عامل اوبونتو 24.04، می‌توانید از مستندات رسمی پارمین کلود برای نصب Node.js استفاده کنید.

همچنین باید بتوانید با Create React App اپلیکیشن بسازید. شما از کامپوننت‌های React استفاده خواهید کرد و به دانش پایه‌ای جاوااسکریپت، HTML و CSS نیاز دارید.

مرحله ۱ — ایجاد یک پروژه خالی

در این مرحله، یک پروژه جدید با استفاده از Create React App ایجاد می‌کنید. سپس پروژه نمونه و فایل‌های مرتبط با آن را که هنگام راه‌اندازی پروژه نصب می‌شوند، حذف می‌کنید. در نهایت، یک ساختار فایل ساده برای سازماندهی کامپوننت‌های خود ایجاد می‌کنید.

برای شروع، در ترمینال خود دستور زیر را برای نصب یک پروژه جدید اجرا کنید:

bash
npx create-react-app styling-tutorial

پس از اتمام نصب پروژه، وارد دایرکتوری آن شوید:

bash
cd styling-tutorial

در یک تب یا پنجره جدید ترمینال، پروژه را با اسکریپت شروع Create React App اجرا کنید. مرورگر با اعمال تغییرات به‌طور خودکار رفرش می‌شود، بنابراین این اسکریپت را در حال اجرا نگه دارید:

bash
npm start

یک سرور محلی در حال اجرا خواهید داشت. اگر پروژه در پنجره مرورگر باز نشد، می‌توانید آن را با آدرس http://localhost:3000/ باز کنید. اگر این را از یک سرور ریموت (مانند سرورهای پارمین کلود) اجرا می‌کنید، آدرس به صورت http://your_domain:3000 خواهد بود.

مرورگر شما با یک اپلیکیشن ساده React که بخشی از Create React App است بارگذاری می‌شود.

شما قرار است مجموعه کاملاً جدیدی از کامپوننت‌های سفارشی را بسازید، بنابراید باید با پاک کردن برخی کدهای پیش‌فرض شروع کنید تا یک پروژه خالی داشته باشید.

ابتدا فایل src/App.js را در یک ویرایشگر متن باز کنید. این کامپوننت ریشه (Root) است که در صفحه تزریق می‌شود.

bash
nano src/App.js

فایلی شبیه به این خواهید دید:

styling-tutorial/src/App.js

javascript
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 را جایگزین کنید تا یک مجموعه تگ خالی <></> برگرداند. این به شما یک صفحه معتبر می‌دهد که چیزی نمایش نمی‌دهد. کد نهایی به شکل زیر خواهد بود:

styling-tutorial/src/App.js

javascript
import React from ‘react’;
import ‘./App.css’;
function App() {
return <></>;
}
export default App;

فایل را ذخیره کرده و از ویرایشگر متن خارج شوید.

در نهایت، لوگوی پیش‌فرض را حذف کنید. شما از آن در اپلیکیشن خود استفاده نخواهید کرد و بهتر است فایل‌های استفاده نشده را حذف کنید. در ترمینال دستور زیر را تایپ کنید:

bash
rm src/logo.svg

اگر به مرورگر خود نگاه کنید، یک صفحه خالی خواهید دید.

اکنون که پروژه نمونه را پاک کردید، یک ساختار فایل ساده ایجاد کنید. این کار به شما کمک می‌کند تا کامپوننت‌های خود را ایزوله و مستقل نگه دارید. یک دایرکتوری به نام components در مسیر src ایجاد کنید:

bash
mkdir src/components

یک دایرکتوری برای App ایجاد کنید:

bash
mkdir src/components/App

تمام فایل‌های App را به آن دایرکتوری منتقل کنید:

bash
mv src/App.* src/components/App

سپس، مسیر Import نسبی در فایل index.js را به‌روزرسانی کنید:

bash
nano src/index.js

دستور Import باید به فایل App.js در دایرکتوری App اشاره کند، بنابراین تغییر مشخص شده را اعمال کنید:

styling-tutorial/src/index.js

javascript
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();

فایل را ذخیره کرده و ببندید. اکنون که پروژه راه‌اندازی شد، می‌توانید اولین کامپوننت خود را ایجاد کنید.


مرحله ۲ — استایل‌دهی به کامپوننت با CSS ساده

در این مرحله، یک کامپوننت Alert نمونه می‌سازید که یک هشدار را در یک صفحه وب نمایش می‌دهد. شما با استفاده از CSS ساده، آن را استایل‌دهی می‌کنید که آن را مستقیماً در کامپوننت Import می‌کنید.

ابتدا کامپوننت Alert جدید را ایجاد کنید:

bash
mkdir src/components/Alert
nano src/components/Alert/Alert.js

یک کامپوننت پایه اضافه کنید که عبارت Alert را برمی‌گرداند:

styling-tutorial/src/components/Alert/Alert.js

javascript
import React from ‘react’;
export default function Alert() {
return <div>Alert</div>
}

سپس فایل App.js را باز کنید:

bash
nano src/components/App/App.js

کامپوننت Alert را Import کرده و آن را داخل یک <div> رندر کنید:

styling-tutorial/src/components/App/App.js

javascript
import React from ‘react’;
import ‘./App.css’;
import Alert from ‘../Alert/Alert’;
function App() {
return (
<div className=”wrapper”>
<Alert />
</div>
)
}
export default App;

فایل را ذخیره و ببندید. مرورگر رفرش می‌شود و کامپوننت شما را نشان می‌دهد.

سپس فایل App.css را باز کنید تا به آن کمی Padding اضافه کنید:

bash
nano src/components/App/App.css

کد پیش‌فرض را با قانون زیر جایگزین کنید:

styling-tutorial/src/components/App/App.css

css
.wrapper {
padding: 20px;
}

وقتی از Create React App استفاده می‌کنید، webpack فایل CSS ای که Import شده را می‌گیرد و آن را در یک تگ <style> در بالای فایل رندر شده در مرورگر اضافه می‌کند. این بدان معناست که می‌توانید CSS را در کنار کامپوننت نگه دارید. اما این همچنین به این معناست که استایل‌های شما دارای دامنه سراسری (Global Scope) هستند که می‌تواند تداخل نام (Name Conflicts) ایجاد کند.

برای بررسی این مشکل، تغییراتی در کامپوننت Alert ایجاد کنید. فایل Alert.js را باز کنید:

bash
nano src/components/Alert/Alert.js

کدهایی اضافه کنید که children، type و title را به عنوان Props دریافت می‌کنند:

styling-tutorial/src/components/Alert/Alert.js

javascript
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,
}

سپس فایل App.js را آپدیت کنید:

bash
nano src/components/App/App.js

یک هشدار ایجاد کنید که به کاربر اطلاع دهد تلاش برای افزودن موارد به سبد خرید ناموفق بوده است:

styling-tutorial/src/components/App/App.js

javascript
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;

افزودن CSS به کامپوننت Alert از آنجایی که کامپوننت Alert یک خطا را نمایش می‌دهد، یک Border اضافه می‌کنید و رنگ آن را قرمز می‌کنید. اما اینجا یک مشکل وجود دارد: شما نمی‌توانید از نام کلاس wrapper برای <div> بیرونی در کامپوننت Alert استفاده کنید، زیرا این نام قبلاً توسط کامپوننت App گرفته شده است.

در این آموزش، شما پیشوند نام کامپوننت را به کلاس اضافه می‌کنید. نام کلاس جدید شما alert-wrapper خواهد بود. فایل Alert.js را باز کنید:

bash
nano src/components/Alert/Alert.js

کدهای مشخص شده را اضافه کنید:

styling-tutorial/src/components/Alert/Alert.js

javascript
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>
)
}

سپس استایل‌ها را اضافه کنید. فایل CSS کامپوننت Alert را باز کنید:

bash
nano src/components/Alert/Alert.css

کد زیر را اضافه کنید:

styling-tutorial/src/components/Alert/Alert.css

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 نمایش می‌دهد.

bash
mkdir src/components/CartSuccess
nano src/components/CartSuccess/CartSuccess.js

داخل کامپوننت، Alert را Import کنید:

styling-tutorial/src/components/CartSuccess/CartSuccess.js

javascript
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>
)
}

سپس فایل CartSuccess.css را باز کرده و استایل‌ها را اضافه کنید:

bash
nano src/components/CartSuccess/CartSuccess.css

styling-tutorial/src/components/CartSuccess/CartSuccess.css

css
.cart-success-wrapper {
border-top: black solid 1px;
display: flex;
flex-wrap: wrap;
}
.cart-success-wrapper h2 {
width: 100%;
}
.item {
margin-right: 20px;
}

اکنون آن را به App.js اضافه کنید:

bash
nano src/components/App/App.js

styling-tutorial/src/components/App/App.js

javascript
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;

این نمایش رنگ و پیام جدید را نشان می‌دهد، اما کامپوننت تو در تو استایل‌های غیرمنتظره‌ای دریافت کرده است. قانون <h2> در کامپوننت Alert روی تگ <h2> در children اعمال شده است. برای رفع این مشکل با CSS خالص، قانون <h2> را در فایل Alert.css کمی خاص‌تر کنید:

bash
nano src/components/Alert/Alert.css

از ترکیب‌کننده فرزند (>) استفاده کنید:

styling-tutorial/src/components/Alert/Alert.css

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;
}

مرحله ۳ — استایل‌دهی با آبجکت‌های استایل (Style Objects)

در این مرحله، کامپوننت‌های خود را با استفاده از آبجکت‌های استایل فرمت‌بندی می‌کنید. این آبجکت‌ها، آبجکت‌های جاوااسکریپتی هستند که از ویژگی‌های CSS به عنوان کلید استفاده می‌کنند.

برای استفاده از آبجکت‌های استایل، ابتدا فایل App.js را باز کنید:

bash
nano src/components/App/App.js

فایل CSS Import شده را حذف کنید و یک آبجکت بسازید:

styling-tutorial/src/components/App/App.js

javascript
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;

سپس CartSuccess را بازنویسی کنید. فایل را باز کنید:

bash
nano src/components/CartSuccess/CartSuccess.js

CSS Import شده را حذف کرده و آبجکت استایل بسازید:

styling-tutorial/src/components/CartSuccess/CartSuccess.js

javascript
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>
)
}

در اینجا باید از فرمت camelCase (مثل marginRight به جای margin-right) استفاده کنید.

سپس فایل Alert.js را باز کنید:

bash
nano src/components/Alert/Alert.js

import './Alert.css'; را حذف کنید و از Prop نوع (type) برای تنظیم پویای رنگ استفاده کنید:

styling-tutorial/src/components/Alert/Alert.js

javascript
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>
)
}

مرحله ۴ — استایل‌دهی با JSS

در این مرحله، از کتابخانه محبوب JSS استفاده می‌کنید. JSS یک کتابخانه برای ایجاد CSS-in-JS است. مزیت اصلی آن در این آموزش این است که نام کلاس‌های پویا (Dynamic) ایجاد می‌کند که از تداخل نام‌ها بین کامپوننت‌ها جلوگیری می‌کند.

ابتدا نسخه مخصوص React کتابخانه JSS را با استفاده از میرور پارمین کلود نصب کنید:

bash
npm install react-jss –registry=https://npm.parmincloud.ir

پس از نصب، فایل App.js را باز کنید:

bash
nano src/components/App/App.js

برای استفاده از JSS، باید تابع createUseStyles را Import کنید. این تابع یک Hook سفارشی ایجاد می‌کند. تغییرات مشخص شده را اعمال کنید:

styling-tutorial/src/components/App/App.js

javascript
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;

اکنون CartSuccess.js را بازنویسی کنید:

bash
nano src/components/CartSuccess/CartSuccess.js

یک Hook سفارشی با createUseStyles ایجاد کنید. برای اعمال استایل روی تگ‌های فرزند (مثل <h2> داخل wrapper)، از علامت & استفاده می‌کنیم:

styling-tutorial/src/components/CartSuccess/CartSuccess.js

javascript
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>
)
}

اگر به مرورگر نگاه کنید، می‌بینید که با وجود استفاده از نام wrapper در این کامپوننت و کامپوننت App، تداخلی وجود ندارد. JSS نام‌های کلاس یکتایی تولید می‌کند.

برای ایجاد استایل‌های پویا با پاس دادن Props در JSS، فایل Alert.js را باز کنید:

bash
nano src/components/Alert/Alert.js

آبجکت استایل را مانند کد قبلی بسازید، اما این بار آن را به تابع createUseStyles پاس می‌دهیم. برای پاس دادن Props، قانون استایل را به یک تابع تبدیل می‌کنیم:

styling-tutorial/src/components/Alert/Alert.js

javascript
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>
)
}

برای جلوگیری از اعمال شدن استایل تگ <h2> روی کامپوننت‌های فرزند (مانند مشکلی که در مرحله ۲ داشتیم)، علامت > را به & > h2 اضافه کردیم.

نتیجه‌گیری

در طول این آموزش، شما چندین کامپوننت قابل استفاده مجدد ایجاد کردید که از تکنیک‌های مختلف استایل‌دهی استفاده می‌کنند. شما یاد گرفتید که چگونه آبجکت‌های استایل و JSS با استفاده از نام‌هایی که دقیقاً مطابق با ویژگی‌های استاندارد CSS هستند، آبجکت‌هایی می‌سازند و کامپوننت‌هایی ایجاد کردید که می‌توانند بر اساس ویژگی‌های دریافتی (Props)، استایل‌ها را به طور پویا تنظیم کنند.

همانند بیشتر تکنیک‌های React، هیچ راه‌حل واحد و بهترین وجود ندارد. در عوض، می‌توانید گزینه استایل‌دهی را انتخاب کنید که بهترین تطبیق (Best Fit) را با پروژه شما داشته باشد. با این گزینه‌ها، می‌توانید با چیزی ساده شروع کنید و با رشد پروژه یا تغییر الزامات، کدهای خود را بازنویسی کنید، در حالی که مطمئن هستید کامپوننت‌های شما همچنان به اهداف استایل‌دهی شما پاسخ می‌دهند.

از همراهی شما با پارمین کلود سپاسگزاریم.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا