برنامه نویسی

React Context: راهنمای تفصیلی

Dead Simple Chat قدرتمند ارائه می دهد JavaScript Chat API که می توانید از آن برای افزودن چت به هر React یا برنامه وب در عرض چند دقیقه استفاده کنید. Dead Simple Chat بسیار قابل تنظیم است و چت برای هر مورد استفاده از چت قابل استفاده است.

معمولاً وقتی می خواهید داده ها را از مؤلفه والد به مؤلفه های فرزند منتقل کنید، از props استفاده می کنید.

اما اگر داده‌ها باید عمیقاً از چندین مؤلفه منتقل شوند، وقتی چندین مؤلفه به داده‌های مشابهی نیاز دارند، استفاده از props برای ارسال داده در درخت مؤلفه دشوار می‌شود.

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

بنابراین وظیفه انتقال دستی لوازم جانبی به تمام اجزای فرزند که به داده های یکسانی نیاز دارند بسیار کاهش می یابد.

بیایید به یک مثال سریع با استفاده از React Context نگاه کنیم.

مثال زمینه واکنش سریع

ما یک برنامه React بسیار ابتدایی با استفاده از React Context ایجاد خواهیم کرد تا آن را ارسال کنیم theme درخت جزء را پایین بیاورید.

این برنامه به کاربران اجازه می دهد تا بین تم های روشن و تاریک جابجا شوند

  1. ایجاد یک ThemeProvider.jsx فایل برای ذخیره منطق ThemeContext ما.
import { createContext, useState } from 'react';

export const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export default ThemeProvider;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما استفاده کرده ایم createContext() روشی برای ایجاد یک زمینه به نام ThemeContext

سپس یک را ایجاد می کنیم ThemeProvider و در ThemeProvider متد، حالت و متدهایی را که می‌خواهیم به همه مؤلفه‌های فرزند منتقل کنیم، اضافه می‌کنیم.

در روش بازگشت، ما در حال افشاگری هستیم theme متغیر حالت و toggleTheme روش به تمام اجزای فرزند با استفاده از پایه value={{ theme, toggleTheme }}

این theme ایالت و toggleTheme متغیر برای همه اجزای فرزند در دسترس خواهد بود.

2. وارد کنید ThemeProvider به شما App.js و بپیچید ThemeProvider اطراف مولفه ریشه شما این اجازه می دهد تا تمام اجزای فرزند به Context دسترسی داشته باشند.

import React from 'react';
import ThemeProvider from './ThemeProvider';
import MainComponent from './MainComponent';

function App() {
  return (
    <ThemeProvider>
      <MainComponent />
    </ThemeProvider>
  );
}

export default App;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3. حالا ما آن را ایجاد می کنیم MainComponent.js فایل برای مصرف Context

import { useContext } from 'react';
import { ThemeContext } from './ThemeProvider';

const MainComponent = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  const themeStyles = {
    backgroundColor: theme === 'light' ? '#fff' : '#333',
    color: theme === 'light' ? '#333' : '#fff',
  };

  return (
    <div style={themeStyles}>
      <h1>Main Component</h1>
      <p>Current Theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
};

export default MainComponent;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کد بالا، ما از useContext قلاب برای واکشی theme متغیر حالت و toggleTheme روش از زمینه

useContext

این useContext روش برای استفاده از زمینه در مولفه های فرزند استفاده می شود. این useContext متد زمینه ای را می پذیرد که مؤلفه فرزند می خواهد از آن استفاده کند و می توانیم متدها و متغیرهای در معرض دید زمینه را استخراج کنیم.

  const { theme, toggleTheme } = useContext(ThemeContext);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مثال های بیشتر با استفاده از React Context

بیایید به چند مثال دیگر با استفاده از React Context و جایی که منطقی است از React Context در برنامه خود استفاده کنید نگاه کنیم.

استفاده از React Context با React Toastify

React Toastify کتابخانه ای است که برای نمایش اعلان های نان تست در برنامه شما استفاده می شود.

اگر می خواهید یک آموزش دقیق در مورد React Toastify یاد بگیرید، می توانید به پست وبلاگ راهنمای کامل React Toastify ما مراجعه کنید.

در حال حاضر، ما یک برنامه اساسی با استفاده از React Toastify ایجاد خواهیم کرد و هدف ما این است که به برنامه اجازه دهیم اعلان‌های نان تست را از هر مؤلفه فعال کند.

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

برای حل این مشکل، می‌توانیم یک Context ایجاد کنیم و روشی را برای نمایش اعلان نان تست در متن اضافه کنیم، و مولفه‌های فرزند می‌توانند از متن استفاده کنند و متد را برای نمایش اعلان نان تست فراخوانی کنند.

  1. ابتدا ما آن را نصب می کنیم react-toastify بسته بندی
npm install --save react-toastify
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2. در ادامه یک فایل به نام as ایجاد می کنیم ToastProvider.js این فایل حاوی ما خواهد بود ToastContext و ToastProvider

import { createContext } from "react";
import { toast } from "react-toastify";

export const ToastContext = createContext();

const ToastProvider = ({ children }) => {
  const showToast = (message, type) => {
    toast[type](message);
  };

  return (
    <ToastContext.Provider value={{ showToast }}>
      {children}
    </ToastContext.Provider>
  );
};

export default ToastProvider;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3. بپیچید ToastProvider اطراف مولفه Root در شما App.js فایل

import React from 'react';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import ToastProvider from './ToastProvider';
import MainComponent from './MainComponent';

function App() {
  return (
    <ToastProvider>
      <MainComponent />
      <ToastContainer />
    </ToastProvider>
  );
}

export default App;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3. ایجاد کنید MainComponent.js فایل برای ذخیره MainComponent. در MainComponent ما از زمینه برای فعال کردن اعلان نان تست استفاده خواهیم کرد

import { useContext } from "react";
import ChildComponent from "./ChildComponent";
import { ToastContext } from "./ToastProvider";

const MainComponent = () => {
  const { showToast } = useContext(ToastContext);

  const handleShowToast = (type) => {
    const message = `This is a ${type} toast!`;
    showToast(message, type);
  };

  return (
    <div>
      <h1>Main Component</h1>
      <button onClick={() => handleShowToast("success")}>
        Show Success Toast
      </button>
      <button onClick={() => handleShowToast("error")}>Show Error Toast</button>
      <ChildComponent />
    </div>
  );
};

export default MainComponent;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

4. یک کامپوننت به نام the ایجاد کنید ChildComponent.js این به ما امکان می دهد از Context در Child Component نیز استفاده کنیم

import { useContext } from "react";
import AnotherChildComponent from "./AnotherChildComponent";

import { ToastContext } from "./ToastProvider";

function ChildComponent() {
  const { showToast } = useContext(ToastContext);

  function triggerToast() {
    showToast("Toast tiggered from child component", "success");
  }

  return (
    <div>
      <h1>Child Componenet</h1>
      <button
        onClick={() => {
          triggerToast();
        }}
      >
        Trigger Toast
      </button>

      <AnotherChildComponent />
    </div>
  );
}

export default ChildComponent;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

5. ما مؤلفه های بیشتری را که فرزند «ChildComponent» نامیده می شود، خواهیم کرد AnotherChildComponent.js

import { useContext } from "react";

import { ToastContext } from "./ToastProvider";

function AnotherChildComponent() {
  const { showToast } = useContext(ToastContext);

  function triggerToast() {
    showToast("Toast tiggered from AnotherChild component", "success");
  }

  return (
    <div>
      <h1>Another Child Componenet</h1>
      <button
        onClick={() => {
          triggerToast();
        }}
      >
        Trigger Toast
      </button>
    </div>
  );
}

export default AnotherChildComponent;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا کد کاملی است که CodeSandbox را اجرا می کند:

%[https://codesandbox.io/s/dazzling-murdock-zig94y?from-embed]

مثال با زمینه های چندگانه

حال بیایید به مثالی نگاه کنیم که از چندین React Context استفاده می کند. با استفاده از یک React Application چند صفحه ای ایجاد خواهیم کرد react-router-dom و دو Context ایجاد می کند که یکی آن خواهد بود ThemeContext برای مدیریت موضوع و یکی دیگر خواهد بود UserContext.

  1. با استفاده از یک برنامه react جدید ایجاد کنید create-react-app

    npx create-react-app multi-context-app
    cd multi-context-app
    
  2. اکنون نصب کنید react-router-dom بسته، که به ما امکان می دهد مسیریابی را در برنامه خود ایجاد کنیم

    npm install react-router-dom
    
  3. اکنون ما خود را ایجاد خواهیم کرد ThemeContext. یک پوشه به نام contexts در داخل پوشه src ایجاد کنید و در آنجا یک فایل به نام ایجاد کنید ThemeContext.js

    // src/contexts/ThemeContext.js
    import { createContext, useState } from "react";
    
    const ThemeContext = createContext();
    
    const ThemeProvider = ({ children }) => {
      const [theme, setTheme] = useState("light");
    
      const toggleTheme = () => {
        setTheme(theme === "light" ? "dark" : "light");
      };
    
      return (
        <ThemeContext.Provider value={{ theme, toggleTheme }}>
          {children}
        </ThemeContext.Provider>
      );
    };
    
    export { ThemeContext, ThemeProvider };
    

    این ThemeContext شبیه ThemeContext است که در اولین مثال خود ایجاد کرده ایم.

  4. بعد زمینه دیگری به نام the ایجاد کنید UserContext، داخل پوشه contexts ما. این UserContext اطلاعات مربوط به کاربر وارد شده را نگه می دارد.

// src/contexts/UserContext.js

import { createContext, useState } from "react";

const UserContext = createContext();

const UserProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  const login = (username, password) => {
    // perform login logic and set the user object
    setUser({ username, email: "user@example.com" });
  };

  const logout = () => {
    // perform logout logic and set the user object to null
    setUser(null);
  };

  return (
    <UserContext.Provider value={{ user, login, logout }}>
      {children}
    </UserContext.Provider>
  );
};

export { UserContext, UserProvider };
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

ایجاد خواهیم کرد Header مؤلفه ای که تم فعلی را نمایش می دهد و به کاربر اجازه می دهد آن را تغییر دهد و ما نیز a ایجاد می کنیم Profile مؤلفه ای که اطلاعات کاربر وارد شده فعلی را نشان می دهد و همچنین به آنها امکان خروج از سیستم را می دهد.

شاید قبلا حدس زده باشید، Header جزء استفاده خواهد کرد ThemeContext و Profile جزء استفاده می کند UserContext.

  1. یک فایل به نام ایجاد کنید src/Header.js این کامپوننت هدر ما را نگه می دارد و کد زیر را به آن فایل اضافه می کند:
// src/Header.js

import { useContext } from "react";
import { ThemeContext } from "./contexts/ThemeContext";
import { Link } from "react-router-dom";

const Header = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <header className={`header ${theme}`}>
      <button onClick={toggleTheme}>Toggle Theme</button>
      <nav>
        <ul style={{ listStyle: "none" }}>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default Header;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کد بالا، ما از ThemeContext و اطلاعات تم فعلی را دریافت کنید و موضوع فعلی را به عنوان className برای سربرگ

ما همچنین تماس می گیریم toggleTheme روشی که توسط ThemeContext زمانی که کاربر روی Toggle Theme دکمه.

  1. فایل دیگری به نام as ایجاد کنید src/Profile.js این کد را برای ما نگه می دارد Profile جزء.

    // src/Profile.js
    
    import { useContext } from "react";
    import { UserContext } from "./contexts/UserContext";
    
    const Profile = () => {
      const { user, login, logout } = useContext(UserContext);
    
      const handleLogin = () => {
        login("myusername", "mypassword");
      };
    
      const handleLogout = () => {
        logout();
      };
    
      return (
        <div className="profile">
          {user ? (
            <>
              <h2>{user.username}</h2>
              <p>{user.email}</p>
              <button onClick={handleLogout}>Logout</button>
            </>
          ) : (
            <>
              <button onClick={handleLogin}>Login</button>
            </>
          )}
        </div>
      );
    };
    
    export default Profile;
    

    این Profile جزء استفاده می کند UserContext. ما ورود و خروج را ساده کرده ایم و اطلاعات کاربر را نمایش خواهیم داد. در کامپوننت پروفایل، دکمه‌های ورود و خروج را نیز اضافه کرده‌ایم که با فشار دادن آن‌ها متدهای Context را برای شبیه‌سازی ورود و خروج فراخوانی می‌کنند.

  2. حال اجازه دهید مسیریابی را در برنامه خود راه اندازی کنیم و دو صفحه ایجاد کنیم Home و Dashboard که از ما استفاده خواهد کرد Header و Profile اجزاء.

    یک فایل به نام as ایجاد کنید src/Home.js که صفحه اصلی ما را نگه می دارد.

// src/Home.js

import React from "react";
import Profile from "./Profile";

const Home = () => {
  return (
    <div className="home">
      <h2>Welcome to My App</h2>
      <p>This is the home page of my app</p>
      <Profile />
    </div>
  );
};

export default Home;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این Home مؤلفه از مؤلفه Profile برای نمایش اطلاعات نمایه استفاده می کند.

فایل دیگری به نام as ایجاد کنید Dashboard.js این مسیر داشبورد را نشان می دهد.

// src/Dashboard.js

import { useContext } from "react";
import { UserContext } from "./contexts/UserContext";

const Dashboard = () => {
  const { user, login, logout } = useContext(UserContext);

  function handleLogin() {
    login("username", "password");
  }

  return (
    <div className="dashboard">
      {user ? (
        <>
          <h2>Dashboard</h2>
          <p>Welcome to your dashboard, {user.username}</p>
        </>
      ) : (
        <>
          <p>You need to be logged in to access the dashboard</p>
          <button onClick={handleLogin}>Login</button>
        </>
      )}
    </div>
  );
};

export default Dashboard;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در Dashboard جزء ما مستقیماً از زمینه برای واکشی اطلاعات کاربر استفاده می‌کنیم، و همچنین یک دکمه ورود به سیستم اضافه کرده‌ایم تا به کاربر اجازه ورود به سیستم را بدهد، اگر کاربر وارد نشده باشد.

  1. فایل App.js را برای وارد کردن ارائه دهندگان، هدر و روترها به روز کنید
// src/App.js

import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Header from "./Header";
import Home from "./Home";
import Dashboard from "./Dashboard";
import { ThemeProvider } from "./contexts/ThemeContext";
import { UserProvider } from "./contexts/UserContext";
import "./App.css";

const App = () => {
  return (
    <Router>
      <ThemeProvider>
        <UserProvider>
          <div className="App">
            <Header />
            <Routes>
              <Route exact path="/" element={<Home />} />
              <Route exact path="/dashboard" element={<Dashboard />} />
            </Routes>
          </div>
        </UserProvider>
      </ThemeProvider>
    </Router>
  );
};

export default App;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا کد کامل در حال اجرا در Code Sandbox است:

%[https://codesandbox.io/s/reverent-rumple-o1pdv6?from-embed]

اکنون یک مثال جامع با استفاده از React Context دیده‌ایم، اکنون اجازه می‌دهیم در مورد اینکه کجا استفاده از React Context منطقی است و در چه سناریوهایی باید از React Context اجتناب شود، بحث کنیم.

سناریوهایی برای استفاده از React Context

React context به ویژه زمانی مفید است که یک حالت جهانی در سراسر برنامه وجود داشته باشد که باید با بسیاری از مؤلفه ها به اشتراک گذاشته شود. در اینجا برخی از سناریوهایی وجود دارد که در آنها استفاده از React Context منطقی است.

  1. مدیریت دولت جهانی: وقتی یک حالت جهانی دارید که باید بین بسیاری از مؤلفه‌ها به اشتراک گذاشته شود، مانند تم، سفارشی‌سازی، پیکربندی برنامه، تأیید هویت کاربر و غیره، پس React Context انتخاب خوبی است.

  2. جلوگیری از حفاری پایه: نمونه ها را هم بحث کرده ایم و دیده ایم. هنگامی که شما نیاز به انتقال داده از طریق چندین مؤلفه دارید، انتقال داده ها از طریق props بسیار دشوار است. با استفاده از React Context، می‌توانید داده‌ها را به‌طور تمیز از درخت مؤلفه خود عبور دهید و در نتیجه کد قابل نگهداری به دست آورید.

  3. اضافه کردن قابلیت استفاده مجدد به کد: با React Context می توانید منطق را مجدداً در برنامه خود استفاده کنید. همانطور که در مثال زیر دیدیم، ما از React Context برای راه‌اندازی Toast استفاده می‌کنیم تا اعلان‌ها را از هر نقطه در درخت کامپوننت نشان دهیم.

توجه به این نکته ضروری است که نباید بیش از حد از Context استفاده کنید. همانطور که در اسناد واکنش رسمی ذکر شده است که “فقط به این دلیل که شما نیاز دارید که برخی از وسایل را در چندین سطح عمیق بگذرانید، به این معنی نیست که باید آن اطلاعات را در متن قرار دهید.”

ابتدا با عبور دادن props به سمت پایین شروع کنید و اگر خیلی دست و پا گیر شد، آن را با استفاده از React Context تغییر دهید.

عبور دادن پایه ها به پایین ترجیح داده می شود زیرا سطحی از شفافیت را در پایگاه کد اضافه می کند.

علاوه بر این، اگر برنامه شما به مدیریت پیچیده ایالت نیاز دارد، ممکن است از یک کتابخانه مدیریت دولتی اختصاصی مانند Redux یا MobX استفاده کنید.

سناریوهایی برای عدم استفاده از React Context

در اینجا برخی از سناریوهایی وجود دارد که باید از استفاده از React Context اجتناب کنید.

  1. ایالت مرتبط محلی: هنگامی که حالت فقط به چند مؤلفه نزدیک مرتبط است، استفاده از React Context بسیار زیاد است و باعث ایجاد پیچیدگی غیر ضروری می شود.

  2. وضعیت به‌روزرسانی مکرر: React context همه مؤلفه‌ها را با استفاده از حالت دوباره رندر می‌کند. اگر یک مقدار حالت به طور مکرر به روز شود و به همه مؤلفه ها مربوط نباشد، باعث مشکلات عملکرد و رندر مجدد غیرضروری مؤلفه ها می شود.

  3. مدیریت مجتمع دولتی: زمینه React برای مدیریت حالت جهانی ساده مناسب است. اگر برنامه شما به مدیریت وضعیت پیچیده و ویژگی های پیشرفته نیاز دارد، استفاده از چیزی مانند Redux یا MobX منطقی تر خواهد بود.

  4. ارتباط جزء به جزء: اگر می خواهید دو مؤلفه فرزند با یکدیگر ارتباط برقرار کنند، پس زمینه React انتخاب خوبی نیست. در این حالت، می توانید وضعیت را بالا ببرید یا عملکردهای برگشت به تماس را ارسال کنید.

  5. ساختارهای داده پیچیده: React Context برای ساختارهای داده مسطح مناسب است. اگر وضعیت شما به یک ساختار داده تودرتو پیچیده نیاز دارد، پس زمینه React ممکن است بهترین انتخاب نباشد و حفظ آن دشوار است و منجر به مشکلات عملکرد می شود.

React Context Pitfalls

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

  1. استفاده بیش از حد از زمینه: استفاده بیش از حد از React Context و حتی React State آسانتر است. افزودن زمینه جدید و حتی وضعیت جدید به برنامه پیچیدگی می‌افزاید، بنابراین هنگام استفاده از React Context باید مراقب باشید و در مواقع ضروری آن را به برنامه خود اضافه کنید.

  2. اتصال محکم قطعات: استفاده بیش از حد از Context در برنامه شما منجر به ایجاد کامپوننت هایی می شود که به شدت با یکدیگر مرتبط هستند و به روز رسانی یک جزء منجر به عوارض جانبی غیرضروری در سایر اجزا می شود. برای جلوگیری از این اجزای طراحی با یک مرز مشخص.

  3. مقادیر متن قابل تغییر: هرگز مقادیر متن را مستقیماً به روز نکنید، همیشه از آن استفاده کنید setState روش یا روشی در ارائه‌دهنده زمینه برای به‌روزرسانی وضعیت ایجاد کنید. به روز رسانی مقدار متن به طور مستقیم منجر به رفتار غیرمنتظره و یافتن اشکالات سخت می شود.

  4. رندرهای غیر ضروری: هنگامی که یک مقدار زمینه تغییر می کند، همه مؤلفه هایی که زمینه را مصرف می کنند دوباره رندر می شوند، این می تواند منجر به مشکلات عملکرد زمانی شود که بسیاری از مؤلفه ها از زمینه استفاده می کنند. از این رو، زمانی که مقدار آن به طور مکرر تغییر می کند، نباید از متن استفاده کنید یا باید زمینه را تقسیم کنید و فقط مؤلفه های مرتبط باید زمینه را که اغلب به روز می شوند مصرف کنند.

نتیجه

در این راهنما، React Context API را بررسی کرده‌ایم و نمونه‌های ساده‌تر و همچنین پیچیده‌تری را مشاهده کرده‌ایم که از زمینه‌های متعدد استفاده می‌کنند.

ما همچنین در مورد سناریوهایی که در آن استفاده از React Context منطقی است، و جایی که باید از آن اجتناب کرد، بحث کرده‌ایم و همچنین به برخی از مشکلات هنگام استفاده از React Context اشاره کرده‌ایم.

امیدوارم این راهنما به شما درک خوبی از React Context بدهد.

این مقاله در ابتدا در وبلاگ DeadSimpleChat منتشر شد: React Context: The Detailed Guide

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

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

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

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