چرا به Context API جدید React نیاز داریم ؟

گردآوری و تالیف : عرفان کاکایی
تاریخ انتشار : 01 آبان 1397
دسته بندی ها : react

چندین سال پیش، Context API به عنوان یک ویژگی آزمایشی با هشدار «این API در آینده می‌تواند بشکند» معرفی شد. با توجه به این که Context API آزمایشی بود، اکثر توسعه دهندگان به اندازه کافی از آن مطمئن نبودند که بخواهند از آن استفاده کنند.

چند ماه پیش، React چیزهای شگفت‌انگیز زیادی را در نسخه ۱۶.۳ معرفی کرد؛ مانند Context API جدید، حالت strict، حالت async و همچنین متدهای lifecycle بروزرسانی شده. Context API جدید با ثبات بوده، موثرتر است و آماده تولید می‌باشد. حال می‌توانید از این API با اطمینان بیشتری استفاده کنید، که در اینجا نحوه انجام این کار را به شما نشان خواهم داد.

Context API چیست؟

Context API روشی برای قادرسازی کامپوننت‌ها برای به اشتراک گذاری داده‌ها است، بدون این که به صورت خارجی از هر کامپوننت به صورت دستی بگذریم.

Context نسبت به زیرشاخه کامپوننت React، مانند یک آبجکت Global است.

چرا به این Context API جدید نیاز داریم؟

تقریبا همه توسعه دهندگان می‌دانند که کامپوننت‌های React ساختاری به مانند یک درخت دارند. یک گره ریشه وجود دارد، که تمام کامپوننت‌ها به آن متصل هستند. در این ساختار درختی، داده‌ها فقط در یک جهت حرکت می‌کنند: بالا به پایین.

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

در اینجا کامپوننت ریشه،‌ اطلاعات درباره موزیک در حال پخش را در بر می‌گیرد، و از طریق propها اطلاعات را به کامپوننت Header و کامپوننت‌های دیگر مانند AlbumTime و PlayButton منتقل می‌کند.

با توجه به این که در React داده‌ها فقط در یک جهت حرکت می‌کنند، وقتی که داده‌ای در سطح nام مورد نیاز است، داده‌ها باید به عنوان یک prop از تمام کامپوننت‌های فرزند بگذرند. گاهی اوقات، این یک کار بسیار خسته کننده برای توسعه دهندگان است. برای رفع این مشکل، بسیاری از افراد از کتابخانه‌های مدیریت state مانند Redux و MobX استفاده می‌کنند.

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

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

مواردی که Context API در آن‌ها پر کاربرد است چه هستند؟

حال ما درک می‌کنیم که Context‌ چگونه مشکل حفاری propها را حل می‌کند. بیایید برخی موارد استفاده از Context را لیست کنیم:

تم‌ها

قابلیت تنظیم تم، یکی از بهترین موارد در تجربه کاربری است. برای مثال وبسایت Medium حالت تیره و روشن را فراهم می‌کند، که خواندن در موقعیت‌های کم نور را راحت‌تر می‌کند. برای پیاده‌سازی تم‌ها، باید هر کامپوننت را با یک رنگ جدید نقاشی کنید، و برخی تصاویر را تغییر دهید؛ پس اگر از Context استفاده نکنیم، نقاشی مجدد تمام کامپوننت‌ها با منتقل کردن تم‌های جدید از طریق propها بسیار سخت است.

برنامه چند زبانه

برای پیاده‌سازی چند زبان در برنامه، باید متن را در تمام کامپوننت‌ها تغییر داده، و آن را با متن ترجمه شده جایگزین کنیم. این مسئله می‌تواند با استفاده از Context به سادگی پیاده‌سازی شود. ما می‌توانیم زبان فعلی را در Context تنظیم کنیم، و پس از آن تمام کامپوننت‌ها در یک درخت کامپوننت عظیم، می‌توانند متن را در زبان انتخاب شده نمایش دهند. با استفاده از این قابلیت، دیگر نیازی به حفاری prop تا خود کامپوننت‌ها نخواهد بود.

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

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

پیش نمایش

در اینجا یک پیش نمایش مختصر از نحوه استفاده از Context را مشاهده می‌کنید. با تغییر دادن تم و زبان، با این پیش نمایش بازی کنید.

لینک صفحه بر روی وبسایت codesandbox.io:

https://codesandbox.io/s/github/haldarmahesh/react-context-demo/tree/master/?from-embed

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

نکته مهم قبل از این که از Context API استفاده کنید

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

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

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

«در توسعه نرم‌افزار، صرف زمان بیشتر بر روی طراحی، از هفته‌ها تلاش بیشتر در آینده جلوگیری می‌کند.»

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

«Context بهتر است که فقط برای داده‌هایی که در سطوح مختلف درخت کامپوننت‌های React استفاده می‌شوند، به کار گرفته شود.»

چگونه Context را در React 16.3+ پیاده‌سازی کنیم؟

گروه React با ساده نگه داشتن روند پیاده‌سازی Context API، لطف بزرگی به ما کرده‌اند. دو مورد نقش اصلی را در این جریان دارند: Provider آبجکت را در Context فراهم می‌کند و Consumer این داده‌ها را از  Contextدر زیرشاخه هضم می‌کند.

بیایید این تم‌ها را پیاده‌سازی کنیم، تا با آن‌ها و جزئیاتشان آشنا شویم.

1. یک Context بسازید

اولین قدم این است که با استفاده از متد create، یک Context‌ بسازید. کامپوننت‌ها در سطوح مختلف از Context مشابه برای دریافت داده‌ها استفاده خواهند کرد.

import React from 'react';

import lightLogo from './../assets/medium_light.png';

import darkLogo from './../assets/medium_dark.png';

export const themeConfig = {

    light: {

        headerBg: '#F7B30C',

        fontColor: 'black',

        bodybg: 'white',

        logo: lightLogo

    },

    dark: {

        headerBg: '#3c3c3c',

        fontColor: 'white',

        bodybg: 'black',

        logo: darkLogo

    }

};

const ThemeContext = React.createContext(themeConfig.light);

export default ThemeContext;

createContext یک جفت کامپوننت Provider و Consumer می‌سازد و defaultValue مرتبط با Context فعلی را دریافت می‌کند. به خط 18 در کد بالا مراجعه کنید.

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

2. Provider

Provider یک کامپوننت است که Consumer‌ را قادر می‌سازد تا در تغییرات اعمال شده به Context شریک شوند. Provider یک prop به نام value را می‌پذیرد و داده‌های داخل این prop برای تمام Consumerهای فرزند در دسترس هستند.

در بسیاری سناریوها، این مقدار باید دینامیک باشد و در runtime تغییر می‌کند. برای مثال در انتخاب تم توسط کاربر از طریق رابط کاربری، که پس از آن می‌توانیم آن را ذخیره کرده، و آن را از state کامپوننت برداریم.

متد toggleTheme که در خط ۱۷ کد زیر وجود دارد، مقدار موجود در state را تغییر می‌دهد و consumerهای فرزند مقدار جدید را دریافت می‌کنند.

در اینجا کامپوننت نمونه را مشاهده می‌کنید که کامپوننت‌های Header‌ و Body را برای Context فراهم می‌کند.

import React, { Component } from 'react';

import Header from './Header.component';

import Body from './Body.component';

import ThemeContext from './context/ThemeContext';

import {themeConfig} from './context/ThemeContext';

class App extends Component {

  constructor() {

    super();

    this.state = {

      theme: 'light'

    }

    this.toggleTheme = this.toggleTheme.bind(this);

  }

  toggleTheme(newTheme) {

    this.setState({

      theme: newTheme

    });

  }

  render() {

    return (

      <ThemeContext.Provider value={themeConfig[this.state.theme]}}>

        <Header toggleTheme={this.toggleTheme}/>

        <Body/>

      </ThemeContext.Provider>

    );

  }

}

export default App;

3. Consumer

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

Prop با نام value که از Provider به Context فعلی در درخت کامپوننت‌ها منتقل شده است، توسط Consumer در متغیر theme گرفته شده است. به خط ۹ در کد زیر مراجعه کنید.

import React, { Component } from 'react'

import ThemeContext from './context/ThemeContext';

export default class Body extends Component {

  render() {

    return (

      <ThemeContext.Consumer>

        {

          (theme) => (

            <div className="body" style={{color: theme.fontColor, background: theme.bodybg}}>

             Some text goes here

            </div>

          )

        }

      </ThemeContext.Consumer>

    )

  }

}

آیا فکر نمی‌کنید که Context API جدید شگفت‌انگیز است؟ حال پیاده‌سازی تم و چندین زبان در یک برنامه بسیار ساده است.

منبع

مقالات پیشنهادی

با API جدید React به نام Context آشنا شوید

در دنیایی پر از محیط های برنامه نویسی گران قیمت، همیشه انتخاب یک عدد از آنها سخت است. آیا می خواهید از Angular معروف استفاده کنید؟ یا وارد شدن به VueJ...

چرا React تا به این حد محبوب است؟

در این مقاله قصد داریم روی محبوبیت ری‌اکت تمرکز کنیم و قصد مقایسه کردن آن با دیگر فریمورک‌ها را نداریم. اگر بخواهیم به صورت سریع دلایلی از محبوبیت ری‌...

چه زمانی پروژه شما به React نیاز دارد ؟

مطمئنا می‌دانید چه زمانی به HTML و CSS نیاز دارید، تمام وب برپایه HTML و بخش مهمی از آن CSS است. فکر کردن به اینکه چه زمانی به جاوااسکریپت نیاز خواهید...

چرا تجربه کاربری برای وبسایت مهم است؟

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