تعیین state و ساختار اولیه‌ی پروژه

Determining the state and Initial Structure of the Project

23 بهمن 1399
تعیین state و ساختار اولیه ی پروژه

در قسمت قبل ساختار کامپوننت های برنامه مان را تعیین کردیم (به صورت خلاصه) که قسمت سخت و مهم کار بود. حالا باید به فکر state باشیم و ببینیم چه چیزهایی درون state قرار خواهند گرفت. من به صورت خلاصه تمام این موارد را برای شما می نویسم:

مواد اولیه (ingredients) که با آن ها همبرگر را می سازیم حتما باید در State مدیریت شوند. احتمالا برای این قسمت یک شیء جاوا اسکریپتی در نظر می گیریم که محتویاتش همان مواد اولیه باشند، به طور مثال:

{meat: 1, cheese: 2}

یعنی گوشت 1 عدد و پنیر 2 ورقه و الی آخر...

همچنین باید بدانیم که کاربر همبرگر را خریده است یا خیر (یعنی مثلا روی دکمه ی purchase یا checkout کلیک کرده است یا خیر). بنابراین درون state چیزی شبیه به حالت زیر را خواهیم داشت:

purchased: true

قسمت سوم state جمع کل هزینه یا total price است که باید آن را به صورت پویا محاسبه کنیم.

این سه قسمت تمامی منابع state ما خواهد بود! بله فقط به همین سه قسمت می توانیم یک برنامه ی عالی و پویا بسازیم. حالا سوالی پیش می آید که این State را در کدام کامپوننت مدیریت کنیم؟ شاید بگویید باید آن را در App (کامپوننت ریشه ای) مدیریت کنیم اما به نظر من این کار درستی نیست. به نظر من بهتر است state را در همان burger builder یا صفحه ی همبرگرساز مدیریت کنیم چرا که تمام موارد state مربوط به ساخت همبرگر است نه کل پروژه؛ به طور مثال اگر بعدا یک صفحه ی check out (صفحه ی نهایی خرید) به برنامه اضافه کنیم، دیگر اهمیتی به مواد اولیه ی انتخاب شده توسط کاربر نمی دهیم بلکه سفارشات کاربر برای ما مهم خواهد بود. به همین دلیل burger builder باید یک کامپوننت stateful باشد (از نوع کلاس-محور) و بقیه ی کامپوننت ها می توانند از نوع Stateless باشند.

حالا که state را طراحی کردیم نوبت پوشه بندی و راه اندازی اولیه ی پروژه است. برای شروع کار من با استفاده از create-react-app یک پروژه ی کاملا جدید ساخته ام. در قسمت های ابتدایی این سری آموزشی با ساخت پروژه توسط create-react-app آشنا شده ایم در صورتی که آن را فراموش کرده اید دوباره به همان قسمت برگشته و مقاله را مطالعه کنید. صفحه ی مخصوص create-react-app در گیت هاب:

https://github.com/facebook/create-react-app

استفاده از CSS Module به روش جدید

در همین ابتدای کار می خواهیم CSS Modules را برای پروژه ی خود فعال کنیم تا مطمئن شویم هنگام کار در پروژه می توانیم از CSS Module ها استفاده کنیم. توجه داشته باشید که در این پروژه می توانید از روش جدید توضیح داده شده در صفحه ی رسمی react استفاده کنید. در واقع با این روش دیگر نیازی به eject کردن پروژه نیست (همانطور که در جلسه ی CSS Module برایتان توضیح دادم). بگذارید روش جدید را برایتان توضیح بدهم:

فرض کنید یک فایل CSS به نام Button.module.css و با محتویات زیر داریم:

.error {
  background-color: red;
}

و یک فایل CSS دیگر به نام another-stylesheet.css نیز داشته باشیم:

.error {
  color: red;
}

حالا فایل اول را که با پسوند module.css تمام می شود به شکل زیر وارد پروژه ی فرضی می کنیم:

import styles from './Button.module.css'; // Import css modules stylesheet as styles

و فایل another-stylesheet.css را به صورت عادی وارد می کنیم:

import './another-stylesheet.css'; // Import regular stylesheet

در این حالت هر فایل CSS ای که پسوند module.css داشته باشد به طور خودکار دارای CSS Module خواهد شد. به طور مثال در کد زیر:

import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet

class Button extends Component {
  render() {
    // reference as a js object
    return <button className={styles.error}>Error Button</button>;
  }
}

خروجی بدین شکل خواهد بود:

<button class="Button_error_ax7yz">Error Button</button>

دکمه ی ما دارای رنگ پس زمینه ی قرمز است اما متن آن (color) قرمز نیست، یعنی استایل های ما scope گرفته اند. بنابراین این نکته ی مهم را یادتان نرود: قابلیت CSS Modules برای هر فایل CSS ای که در انتهای نامش دارای module.css باشد، فعال خواهد شد و دیگر نیازی به eject کردن پروژه نیست اما اگر دوست دارید از روش قدیمی کار را انجام دهید قسمت زیر را مطالعه کنید.

استفاده از CSS Module به روش قدیمی (eject کردن پروژه)

ترمینال VSCodeرا باز کرده و دستور زیر را در آن اجرا کنید:

npm run eject

با اجرای این دستور از شما سوال می شود:

Are you sure you want to eject? This action is permanent.

سوال برای اطمینان یافتن از اجرای این دستور است. همانطور که گفتم اگر این دستور را اجرا کنید راه بازگشتی به حالت قبلی ندارید. حرف y را (مخفف yes) وارد کرده و اینتر بزنید. پس از اجرا شدن این دستور دو پوشه ی جدید برایمان ساخته می شود:

  • scripts
  • config

در پوشه ی config دو فایل برای ما اهمیت دارند:

  • config.dev.js
  • confgi.prod.js

webpack یک ابزار برای bundle کردن فایل های ما است؛ به زبان ساده تر webpack فایل های ما را مرتب کرده و با هم ادغام می کند و به صورت یک مجموعه به کاربر پاس می دهد. به طور مثال ما در فایل جاوااسکریپت خود دستور import را برای فایل های css استفاده کرده ایم که در حالت عادی غلط است اما webpack متوجه منظور ما شده و فایل ها را خودش مرتب می کند.

ابتدا به فایل webpack.config.dev.js بروید، در حدود خط 103 به قسمت module می رسیم، سپس در حدود خط 162 به قسمت test برای فایل های CSS می رسیم. حالا در همان قسمت باید کدهای زیر را ببینید:

test: /\.css$/,
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1,
                },
              },

قسمت oprions را به شکل زیر تغییر دهید:

options: {
                  importLoaders: 1,
                  modules: true,
                  localIndentName: '[name]__[local]__[hash:base64:5]'
},

Modules:true به ما اجازه می دهد که از CSS Modules استفاده کنیم. سپس localIndentName کاری می کند که name (یعنی نام کلاس های CSS) به صورت محلی (local) ذخیره شوند. Hash اضافه شده در آخر نیز مسئول تعیین hash است تا استایل ها یکتا باشند و روی کلاس های دیگر اعمال نشوند (override رخ ندهد).

حالا می توانیم همین کدهای قسمت options را کپی کرده و به فایل webpack.config.prod.js برویم. در حدود خط 181 به قسمت use در قسمت CSS می رسید. مقدار options را به این شکل تغییر دهید:

use: [
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 1,
            modules: true,
            localIndentName: '[name]__[local]__[hash:base64:5]',
            minimize: true,
            sourceMap: shouldUseSourceMap,
         },
},

با این کار تغییر مورد نظر را هم برای مرحله ی توسعه ی برنامه (فایل webpack.config.dev) و هم در مرحله ی تولید (یعنی نهایی شدن برنامه و قرار گیری روی هاست - فایل webpack.config.prod) ایجاد کرده ایم چرا که نمی خواهیم هنگام ارسال برنامه به سرور به مشکل برخورد کنیم.

نکته ی مهم: در این آموزش من در فایل webpack.config.js به دنبال این قسمت می گردم:

{
  test: /\.css$/,
  ...
}

اما در نسخه های جدید تر create-react-app، این قسمت به شکل زیر درآمده است:

{
  test: cssRegex,
  exclude: cssModuleRegex,
  ...
}

بنابراین اگر حالت اول را ندیدید نگران نشوید. اگر نسخه ی شما جدید است و با حالت دوم روبرو هستید باید این قسمت در فایل webpack.config.js را به شکل زیر دربیاورید:

{
  test: cssRegex,
  exclude: cssModuleRegex,
  use: getStyleLoaders({
      importLoaders: 1,
      modules: true,
      localIdentName: '[name]__[local]__[hash:base64:5]'
  }),
}

همچنین در آخرین نسخه ی create-react-app دیگر فایل webpack.config.prod.js را نداریم و فقط همان فایل webpack.config.dev.js به شما داده می شود. بنابراین فقط همان را ویرایش کنید.

از این به بعد فایل های CSS دارای scope خواهند بود. به طور مثال فایل App.css که در فایل App.js وارد (import) شده است، فقط و فقط مخصوص همان کامپوننت (کامپوننت App) است و در فایل های دیگر اعمال نخواهد شد. البته باید دستور import را کمی تغییر دهیم:

import classes from './App.css';

شما می توانید هر نامی به جای Classes قرار دهید (مثلا styles). مهم این است که classes در اینجا یک شیء جاوا اسکریپتی است که کلاس های فایل App.css را در خود نگه می دارد.

همانطور که گفتم شما می توانید از هر کدام از این روش ها که دوست دارید استفاده کنید. هیچ کدام از این روش ها تاثیر آنچنانی روی پروژه ی ما ندارند بلکه هدف ما فقط scope دهی به فایل های استایل است که هر دو روش این کار را برایمان انجام می دهند.

مرتب کردن پروژه

برای شروع کار فایل logo.svg را حذف کرده و  محتوایت فایل App.js را نیز بدین صورت تر و تمیز کنید:

import React from 'react';

function App() {
  return (
    <div>
      
    </div>
  );
}

export default App;

سپس فایل App.css را نیز حذف کنید.

درون فایل index.css (مسئول استایل های سراسری کل پروژه) می خواهیم فونت را تغییر دهیم. به google fonts رفته و open sans را کلیک کنید. از سربرگ customize علاوه بر Regular حالت bold را هم انتخاب کنید:

انتخاب حالت bold و regular (حالت bold را برای تیتر ها و متن های ضخیم میخواهیم)
انتخاب حالت bold و regular (حالت bold را برای تیتر ها و متن های ضخیم می خواهیم)

سپس از سربرگ Embed کد ارائه شده را برای خودتان کپی کنید. به پوشه ی public در پروژه ی خودمان بروید و فایل index.html را پیدا کنید. حالا بالای تگ <title> کد کپی شده را paste کنید. همچنین نام title را به MyBurger تغییر دهید:

<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" rel="stylesheet">
<title>MyBurger</title>

در قسمت بعد به سراغ پیاده سازی ساختار کامپوننت هایمان خواهیم رفت.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش ری اکت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.