با این چند ترفند ساده برنامه React بهتری بسازید

در اینجا لیستی از ترفند های شگفت‌انگیز آورده شده است که می‌توانید برای بهبود سریع برنامه‌های React خود استفاده کنید.

این نکات نه تنها کد شما را تمیزتر و قابل اعتمادتر می‌سازد، بلکه هدف آن این است که تجربه توسعه شما را راحت‌تر و به طور کلی لذت‌بخش تر کند.

جایگزینی Redux با React Query

هر چه برنامه شما بزرگ‌تر باشد مدیریت وضعیت در بین کامپوننت‌های شما دشوارتر می‌شود. بنابراین ممکن است به دنبال یک کتابخانه مدیریت وضعیت مانند Redux باشید.

اگر برنامه‌های شما متکی به داده‌هایی باشد که از API دریافت می‌کنید، اغلب از Redux برای واکشی آن وضعیت سرور و سپس آپدیت وضعیت برنامه شما استفاده می‌شود.

اول از همه، React Query به شما امکان کنترل بیشتر درخواست‌های HTTP را در برنامه‌های React از طریق hookهای مفید، همراه با قابلیت واکشی مجدد داده‌ها می‌دهد. همچنین این امکان را برای شما فراهم می‌کند تا اغلب بدون نیاز به آپدیت دستی وضعیت، به طور یکپارچه وضعیت را در بین اجزای برنامه خود مدیریت کنید.

در اینجا نحوه تنظیم React Query در فایل index.js آورده شده است:

import { QueryClient, QueryClientProvider } from 'react-query'
import ReactDOM from "react-dom";

import App from "./App";

const queryClient = new QueryClient()

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  rootElement
);

در اینجا ما در حال راه‌اندازی یک query client هستیم که یک کش را برای ما تنظیم می‌کند تا هر گونه درخواستی را که ما قبلا ساخته‌ایم را به آسانی مدیریت کنیم. همچنین یک کامپوننت query client provider را تنظیم کرده‌ایم تا آن را به کل درخت component ارسال کنیم.

چگونه می‌توانیم با React Query درخواست دهیم

شما می‌توانید درخواست ها را با useQuery hook بسازید، که یک identifier برای کوئری خود بگیرید (در این حالت، از آنجا که ما داده‌های کاربر را واکشی می‌کنیم، آن را “user” می‌نامیم)، به علاوه تابعی که برای واکشی آن داده‌ها استفاده می‌شود.

import { useQuery } from "react-query";

export default function App() {
  const { isLoading, isError, data } = useQuery("user", () =>
    fetch("https://randomuser.me/api").then((res) => res.json())
  );

  if (isLoading) return "Loading...";
  if (isError) return "Error!";

  const user = data.results[0];
  return user.email;
}

همانطور که مشاهده می‌کنید، React Query مراقب مدیریت این وضعیت‌های مختلف است که می‌تواند هنگام واکشی داده های ما صورت گیرد. دیگر نیازی به مدیریت خود این وضعیت‌ها نیست، ما فقط می‌توانیم آن‌ها را از آنچه که از useQuery برگردانده می‌شود دوباره تشکیل دهیم.

بخش مدیریت وضعیت (state management) useQuery از کجا وارد عمل می‌شود؟

اکنون که داده‌های کاربر را واکشی کردیم و آن را در کش داخلی ذخیره کردیم، تنها کاری که باید انجام دهیم تا بتوانیم از آن در سایر کامپوننت‌ها استفاده کنیم فراخوانی useQuery() با کلید “user” است که با آن مرتبط هستیم:

import { useQuery } from "react-query";

export default function OtherComponent() {
  const { data } = useQuery('user');
    
  console.log(data);
}

React Context را با Custom Hook راحت‌تر کنید

React Context راهی عالی برای ارسال داده‌ها از طریق درخت component ما است. این به ما امکان می‌دهد بدون نیاز به استفاده از prop های کاربر داده را به کامپوننتی که می‌خواهیم ارسال کنیم.

برای مصرف context در یک کامپوننت تابع React از useContext استفاده می‌کنیم.

با این حال، برای انجام این کار یک مشکل جزئی وجود دارد. در هر کامپوننتی که می‌خواهیم تا دادده‌های ارسالی به کانتکس را مصرف کنیم باید آبجکت کانتکس ساخته شده را ایمپورت کنیم و React را هم ایمپورت کنیم تا useContext hook را به دست آوریم.

به جای اینکه هر بار که می‌خواهیم از کانتکس بخوانیم مجبور باشیم چند دستور import را بنویسم می‌توانیم به سادگی یک React hook سفارشی بسازیم.

import React from "react";

const UserContext = React.createContext();

function UserProvider({ children }) {
  const user = { name: "Reed" };
  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}

function useUser() {
  const context = React.useContext(UserContext);
  if (context === undefined) {
    throw new Error("useUser in not within UserProvider");
  }
  return context;
}

export default function App() {
  return (
    <UserProvider>
      <Main />
    </UserProvider>
  );
}

function Main() {
  const user = useUser();

  return <h1>{user.name}</h1>; // displays "Reed"
}

در این مثال، ما داده‌های کاربر را بر روی کامپوننت سفارشی UserProvider خود ارسال می‌کنیم، که یک آبجکت user را می‌گیرد و در اطراف کامپوننت Main قرار می‌دهد.

ما یک useUser hook داریم تا با سهولت بیشتری آن کانتکس را مصرف کنیم. ما فقط باید hook خودمان را ایمپورت کنیم تا User Context را در هر کامپوننتی که می‌خواهیم، مانند کامپوننت Main، مصرف کنیم.

مدیریت Context Providerها در یک کامپوننت سفارشی

تقریبا در هر برنامه React ای که می‌سازید، به تعدادی Context provider نیاز دارید.

مقاله‌های مرتبط:

ما نه تنها به Context provider ها برای React Context ای که می‌سازیم نیاز داریم، بلکه از کتابخانه های دیگری که به آن‌ها اعتماد می‌کنیم (مانند React Query) برای ارسال ابزارهای خود به کامپوننت‌های مورد نیازمان، نیاز داریم.

هنگامی که کار بر روی پروژه React خود را شروع می‌کنیم، اینگونه به نظر می‌رسد:

ReactDOM.render(
  <Provider3>
    <Provider2>
      <Provider1>
        <App />
      </Provider1>
    </Provider2>
  </Provider3>,
  rootElement
);

در رابطه با این آشفتگی چه کاری می‌توانیم انجام دهیم؟

به جای قرار دادن همه context provider ها در فایل App.js یا فایل index.js، ما می‌توانیم کامپوننتی به نام ContextProviders بسازیم.

این به ما امکان می‌دهد تا از children prop استفاده کنیم، سپس تنها کاری که باید انجام دهیم این است که همه این providerها را در یک کامپوننت قرار دهیم:

src/context/ContextProviders.js

export default function ContextProviders({ children }) {
  return (
    <Provider3>
      <Provider2>
        <Provider1>
          {children}
        </Provider1>
      </Provider2>
    </Provider3>
  );
}

سپس، کامپوننت ContextProviders را در اطراف برنامه می‌گذاریم:

src/index.js

import ReactDOM from "react-dom";
import ContextProviders from './context/ContextProviders'
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <ContextProviders>
    <App />
  </ContextProviders>,
  rootElement
);

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

وقتی نوبت به کار با کامپوننت‌ها می‌رسد، ما به طور معمول داده‌ها را با کمک propها ارسال می‌کنیم. ما یک prop name می‌سازیم و آن را برابر با مقدار مناسبش می‌گذاریم.

با این حال، اگر props زیادی داشته باشیم که باید به یک کامپوننت ارسال شوند، آیا لازم است همه آن‌ها را به صورت جداگانه لیست کنیم؟

نه، لازم نیست.

یک روش بسیار آسان برای اینکه بتوانیم همه props که می‌خواهیم را بدون نیاز به نوشتن همه prop nameها و مقادیر مربوط به آن‌ها ارسال کنیم استفاده از الگوی {…props} است.

این شامل قرار دادن همه داده‌های prop ما در یک آبجکت و گسترش همه این propها به صورت جداگانه به کامپوننتی است که می‌خواهیم به آن ارسال کنیم:

export default function App() {
  const data = {
    title: "My awesome app",
    greeting: "Hi!",
    showButton: true
  };

  return <Header {...data} />;
}

function Header(props) {
  return (
    <nav>
      <h1>{props.title}</h1>
      <h2>{props.greeting}</h2>
      {props.showButton &amp;&amp; <button>Logout</button>}
    </nav>
  );
}

فراگمنت ها را با استفاده از React fragment مپ کنید

تابع .map() در React به ما امکان می‌دهد تا یک آرایه را بگیریم و آن را تکرار کنیم، سپس داده‌های هر المنت را در برخی از JSX ها نمایش دهید.

با این حال، در برخی موارد، ما می‌خواهیم بیش از این داده‌ها را تکرار کنیم اما نمی‌خواهیم آن‌ها را در یک المنتclosing JSX  برگردانیم. شاید با استفاده از المنت enclosing JSX اعمالات خود را بتوانیم تغییر دهیم یا به سادگی نمی‌خواهیم المنت دیگری را به DOM اضافه کنیم.

یک نکته شناخته شده برای اینکه بتوانید مجموعه ای از داده‌ها را تکرار کنید و المنت والد را به عنوان المنت HTML نداشته باشید، استفاده از React.Fragment است.

با استفاده از فرم دست ساز React fragmentها می‌توان آن را به عنوان key prop ارائه داد که برای هر المنتی که روی آن تکرار می‌شود لازم است.

import React from 'react'

export default function App() {
  const users = [
    {
      id: 1,
      name: "Reed"
    },
    {
      id: 2,
      name: "John"
    },
    {
      id: 3,
      name: "Jane"
    }
  ];

  return users.map((user) => (
    <React.Fragment key={user.id}>{user.name}</React.Fragment>
  ));
}

توجه داشته باشید که ما نمی‌توانیم از key prop مورد نیاز برای جایگزین فراگمنت کوتاه شده استفاده کنیم: </><>.

خروج از نسخه موبایل