Галоўная / Артыкулы

Выкарыстоўвайце React Context для стварэння спяльной асяроддзя, а не як проста папка для зберагчэння дадзеных.

Кантэкст распрадзеляе значэннія праз дрэво; ён не візначае прыналежнасць, не адкладзіць межы і не стварае модэлі стану. Лепш выбіраць спецыялізаваныя прадастчыкі і рэальныя засобы для керавання станам сервера.

Выдавец: REACTAPP.TOP10 хв чытання2308 слоў

Крыніцы: Most Developers Use React Context for the Wrong Problems

Перадача пропаў не завжды ўскладнюе архітэктуру

React Context часта выступае як швыдкае рашэння. Значэнне пераходзіць між трыма компонентамі, якія яго ніколі не выкарыстоўваюць. Іншаму экрану патрэбны даны нынешняга карыстальніка. Модальное вікно павінна ачыцца з глыбокага рэверсу дрэва. Перадача пропаў становіцца вялікай проблемай, таму з’яўляецца provider, і дрэва раптам стае адносна чыстым.

Проміжныя компоненты пазбавляюцца невыкарыстоўваных пропаў. Глыбокія дзецкія компоненты чытаюць тое, што ў іх патрэбна, за дапамогою хука. Такая структура здаецца болей цярпячай, чым перадача таго ж аргумента праз кожны слой.

Этая „косметычная“ перамога можа заслоніць болей глыбокыя пытанні: чы важна ўзагалі тое значэнне знаходзіцца в Context?

Кантэкст рашае адзін проблема. Абяцелюбы можа публікаваць значэнне для своіх наследнікаў без неабходнасці праходжання яго праз кожны промежуточны файл. Ён не выявляе, дзе павінен знаходзіцца стан, як часта павінны апдэйтавацца корыстувальнікі, чы розныя значэнні павінны дзеліць адно скарбніцу, чы і які компонент володзіць рабочым працэсам.

Этыя рашэнні застаюцца. Кантэкст можа іх сховаць, таму што доступ становіцца невідным. Дзецінскі компонент можа чытаць даныя без неабходнасці ях адзначаць у прынтапах. Прадастальнік можа скарыстацца рознымі, несувязанымі поламі, таму што все выглядае як “глобальнае”. Невялікі апдэйт можа распрострацавацца да дзесяткаў корыстувальнікаў, якія дзеляць адным об’ектам кантэкста. Компонент, які няветна мае быць перадуваемым, можа залежаць ад прадастальніка, які існуе толькі на адной сторонцы.

Слабась не ў API. Слабась — у выкарыстоўванні простыяго доступу як замены для болей чыстага власніка.

Prop drilling мае паслязьвістную рэпутацыю, таму што павтарэнне ўсё відчуваецца. Значэння пачынаецца з высокага рэвэлю, пераходзіць праз элементы лейауту і нарэшце доходзіць да таго элемента, якому ён патрэбен. Серэднія шары выглядаюць як сістэмы водапрацоўкі, таму Context здаецца апгрэйдам.

Іноды такое павтарэнне ўособліва корыстнае — яно паказвае месца выходу, на якія галузі вплывае значэння, а таксама як далека праходзіць гэта залежнасць. Prop-ы дазволяюць шукаты вхідныя даны. Калі значэння змінюецца або знікае, яго парадукты застаюцца локальнымі і очывіднымі.

Context стырае гэты шлях — наступны элементы можаць пачаць працаваць без неабяжнай адчынкі промежуточных элементаў. Дрэва все ўсё застаецца залежным ад падаўчыка, але гэтыя зв’язкі больш не праказваюцца на інтэрфейсе элемента.

Гэта не значыць, што кожны дзейнік з довгой лямою прыладоў павінен застацца. Калі вялікі паддрэв справжньа дзеліць адна прычына, вікорыстоўванне нітэй стае зайвам. Памылка заключаецца ў тым, што кожны павтараючыся прылад лягчэйша як доказ таго, што не хватает кантэксту.

Інодзе значэнне ўздымаецца занадта высока праз неправільную прыналежнасць. Старонка зберагае чэрнавік дыялогу і перадае яго праз калькі слоёў да формы. Кантэкст мог бы спрыяць лёгшаму доступу, але болей моцныя прыемы дызайну можа дазволіць форме чы розмовнаму вікну кераваць гэтым чэрнавікам.

Інодзе складанне адменшае серэдні ўскок. Абяцель можа стварыць элемент, які патрэбуе дадзеных, і перадаць гэты элемент як children у лейаут. Лейаут ніколі не даведаецца пра гэтую залежнасць.

Павтараючыся прылады — гэта сімптам. Кантэкст — толькі адна з мераў, і ён не являецца стандартным дыягназам.

Кантэкст не ператварае локальны стан у глобальны стан безпечна

Часта практыка — ствараць спецыяльны кантэкст, калі калькі компанентаў павінны адкорэгаваць той самы стан. Прадастальнік храніць значэнні, выдае функцыі для ўстановкі значэнняў, а кожны з наследнікаў можа яе чытаць або запісваць.

Часта все пачынаецца проста:

const AppContext = createContext(null);

function AppProvider({ children }) {
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [activeModal, setActiveModal] = useState(null);
  const [selectedRecord, setSelectedRecord] = useState(null);
  return (
    <AppContext.Provider
      value={{
        sidebarOpen,
        setSidebarOpen,
        activeModal,
        setActiveModal,
        selectedRecord,
        setSelectedRecord,
      }}
    >
      {children}
    </AppContext.Provider>
  );
}

Даступ да даных знаходзіцца ў аднам месцы, пры тым значэнне стану застаецца неясным. Візыбельнасць бокавай панелі, тое, які модальны вікнік ўвімкнуты, і якае запіс выбрана, часта належачы да разных функцый і працююць за розным графікам.

Тады будзь-які з наследнікаў у дрэве можа безпасебна перапісваць даны, хранячыяся у прадастальніку. Радок у табліце можа выбраць запіс, ачыніць модальны вікнік і закрыць бокавую панелю. Компаненты не выражаюць своіх намераў; яны прыходзяць да спакульнаных полей і ствараюць тую комбінацыю, якая ў іх патрэбна.

Пасуе невыразныя зв’язкі. Модальное вікно прыпускае, што выбор ужэ існуе. Табліца прыпускае, што закрыцце модальнага вікна скасоўвае выбор. Бокавая панель рэагуе на працэсы, якія ёй не належаць. Гэтыя зв’язкі не фіксуюцца ў рэдзюсеры, операцыях чы граніцах функцый — яны існуюць толькі таму, што багато компонентаў можа вызываць багато функцый для змены значэнняя.

Перанесенне поль у кантэкст толькі перамешчае ўсё на дыску. Яснасць значэння не падае автаматычна.

Моцнейшы прадаўець выкладзе операцыі заместо простых функцый для змены значэнняя, і толькі для адной цалесапраяжанай задачы. Сістэма дыялога можа запрошваць openDialog і closeDialog. Прадаўець аутанізацыі можа выкладзе даныя сесіі і операцыі для входу. Прадаўець тэм можа выкладзе тэкушчую тэму і спецыяльную функцыю для яе аднавлення.

Не зупіняйцеся на тым, што «калькі компонентаў патрэбуе доступ». Задайце сабе пытанне, чы раздзеляюць яны аднаковы цыкл жыцця і адну задачу.

Адзін об’ект кантэксту можа стварыць вялічзю паверхню апдэйтаў

Кантэкст таксама распадзяе абнаўленні. Калі зменяецца значэнне прадаўцы, корыстувальнікі гэтага кантэксту можу практычна перзробіць відобразэнне. Гэта нормальна, калі значэнне являе сабою адзін пункт прыемлівалення і корыстувальнікі дзейсна залежаць ад яго змян.

Проблемы пачынаюцца, калі адзін прадаўцы сумачвае значэнняя з частотамі апдэйтаў, якія не ўзаемна асоцыяваны.

function ApplicationProvider({ children }) {
  const value = {
    user,
    theme,
    locale,
    notifications,
    sidebarOpen,
    featureFlags,
    liveJobStatus,
  };

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

Пераключальнік тэмы не павінен узневажаць табліцу, якой была патрэбна толькі выбраная запісь. Флаг адкрытага бокавога панелі не павінен апдэйтаваць форму, якой быў патрэбны толькі ідэнтыфікатор карыстальніка. Аднароджэнне гэтых поль у адзіны об’ект робіць кожнага корыстувальніка чутлівым да кожной змены, як толькі вы не будзеце астаточна запам’ятаваць і раздзеляць кантэксты.

Команды інодзе з’являюць косцы толькі пасля аналізу. Да таго часу багатыя функцыі ужо імпортуюць гэты мега-хук. Раздзелэнне вымагае знаходжэння кожнага корыстувальніка і адлічэння, каторую частку кожны з іх на самай працоўвалі.

Лепшае выбаранне — вузкія прадастчыкі, які працуюць у адпаведным тэнцы выканання апдэйтаў. Размясціце элементы UI з высокай частотай змян у адным месцы, а стабільныя даны сэсіі — ў іншым. Зберагаюце значэння прадастчыкаў у кэш, калі інача ідэнтычнасць об’екта зменялася бы ў кожны раз пад час атрыбутавання. Пераканайцеся ў рэзультатах перш чым аднаўляць “яшчэ адну польку” у існуючы набор даных.

Кантэкст можа замаскуваты відсутныя межы компанентаў

Калі падключэнне якога-небудзь функцыяналу ёст крыхкім, кантэкст можа замаскуваты відсутную межу. Рэдагувальнік продукту, які тылова чытае інформацыю пра актыўны продукт, чэрнавік, прабы валідазіі, правыя доступу і статус мутацыі з кантэкста адзінаго разліку, можа мяць сэнс толькі на тым разліку.

Дзеяныя залежнасці ёсць адпаведна неявнымі, таму што яны опісваюць сераўак, а не даны функцыяналу — тэму, локалізацыю, маршрутызацыю, спяльнага кліента HTTP. Такія залежнасці зазвычай ёсць шырокімі і стабільнымі.

Даныя фічараў разныя. Іх адклейванне ў Context усувае непатрэбны шум пропаў, але падвышае залежнасць архітэктуры. Відсутнасць пропаў не значыць відсутнасць залежнасцей; часта гэта означае, што залежнасці перашлі за межы віду.

З’ясавайце, чы можна зрозумець і працавацы з компонентам парадульна да провайдэра, які яго наразе абгортае. Якшо адказ «нет», значыць Context можа компенсаваць недастатак чыстага кантракту пропаў або складання.

Context часта выкарыстоўваецца заместо належнага керавання станам сервера

Іншы неправільны спосаб — заполненне Context адзяванымі дадзенымі таму, што іх патрэбна калькі компонентаў. Провайдэр запрашвае дадзеныя раз, зберагае адпаведны адказ і выкладзе дадзеныя, стан завантажэння, памылкі і можнаць перзавантажыць іх. Гэта выглядае як спяльны шар дадзенаў без дапамогі іншай бібліятэкі.

Рэальны стан дзеўеру быстра выклікае патрэбу ў дадатковых мерах: адмахоўванні падобных запытак, правілах адкладання праверкі дадзеных пакуль яны не старэе, перапрыбутках, анулюванні запытак, структураванні дадзеных у сторунках, апдэйтах пасля змян і заставе паказу прыкладных дадзеных пад час апцэнтрыкацыі.

Кантэкст не забезпечвае нічога з гэтага. Ён проста перадае тое, што вырахаваў прадастальер.

Прадастальер паступова стае ручным кэшам. Компаненты залежнаць ад яго особлівасэй апцэнтрыкацыі. Змяны ведуцься ручна ў спаканаваных масівах. Разныя прадастальеры ствараюць адносна разныя способы загрузкі і обработкі памылак. Адключэнне адпаведнага маршруту можа прывесты да вымыць кэшу; падключэнне двух прадастальераў можа спрычыніць двойную загрузку дадзеных.

Існуюць спецыяльныя бібліятэкі дадзеных, таму што уядзеньне на даляжыні мае іншы цыкл жыцця, чым локальны стан UI: власнасць на дзеўеры, свежасць дадзеных, кэшаванне, анулювання кэшу, канкурэнція і способы выключэння.

Кантэкст можа распрацоўваць настроены кліент або стабільную залежнасць функцыяй. Рэдка калі гэта правільная альтэрнатыва для паўтарачога стварэння коордынаціі запытоў за дапамой звычайных useState і useEffect. Фокусаваны прадастальнік, які коордыnuе даны сервера з адным прабэгам работы, можа застацца эфектываў, але чыненне даных доступнымі ў всіх месцах не рашае проблему сінхронізацыі.

Чыненне пэйлоаду доступным — гэта не тая ж самая дысціпліна, як кераванне даляённымі данымі.

Кантэкст — не замена мадэлі стану

Калі прабег работы стае сложнейшым, команды інодзе перакладаюць яго ў Кантэкст, каб кожны крок могаў бачыць тыя ж поля. Працэсы апраўлення, налагоджэння, рэдагавання і багатакроковыя формы часта заканчваюцца так.

Гэта можа працаваць, калі прадастальнік прэдставляе адны прабег работы і дазваляе кераванне пераходамі. Але гэта стае нестабільным, калі Кантэкст ёсць проста кантэйнер для полей і функцыяй ўстановкі значэнняў.

Праграма для адміністрування прайс-ліста можа мяць поля з адрэсай, даныя платаў, выбор спосабу даставкі, тэперашні крок, памылкі верыфікацыі, флагі завантажэння, флагі модальных вікнаў, загальную суму і багато іншых элементаў для налаштавання. Кожны падэлемент можа незалежна мяніць будзь-кантэнт.

Аднараванне сховішча не ўзначае візначэння правіл. Змена краіны можа вымагаць анулювання выбору спосабу даставкі; змена спосабу даставкі можа вымагаць перыякання загальнай сумы. Пераворачэнне назад можа заставіць дзеякі поля застацца без змены, а іншыя сталаць нэваліднымі. Неудача платэжа можа змяніць ход задання, не вычысцываючы адрэсу.

Гэтыя зв’язкі вымагаюць мадэлі стану — рэдукероў або явных операцый, якія кодуюць дазволеныя пераходы. Кантэкст можа распадзіць гэтую мадэль; сам кантэкст не ёсць мадэллю.

Без правіл з’являюцься немагчымыя комбінацыі: крок платэжа без правамернай доставкі, адначасовая наявнасць стану «успех» і «памылка», варыянты доставкі, якія належаць да паканейшага адрэсу. Вам не обавязкова якаясь формальная бібліятэка машын станоў. Вы все раве должны чытальна паказаць, якія факты ёсць самастоятэльнымі, якія комбінацыі ёсць дазволенымі, і якія змяны перапісуюць калькі поля пад час адной пераходу.

Кантэкст дапамагае стварыць хорашую мадэль. Ён не можа вывяліць заплутаную мадэль проста падняўшы яе на вышэйшы роўень у іерархіі.

Глобальны доступ: чы можа ён аслабіць права власніка?

Значэнні ў Кантэксце лёгка чытаць і лёгка запісваць з многах месцаў. Зручнасць можа раз’ядзіць права власніка.

Кантэкст паведамленняў, які апошневаецца працэйнікамі сеткі, формамі, сторанкамі і фонавымі задачамі. Кантэкст выбору, які мутуюцца за дапамогою табелей, дыялогавых вікнаў, скораходоў і змян маршрутаў. Кантэкст праганаў, які запісваецца безпасова кожным элементам управління, які паказвае настройку.

Калі багато пісцаў выкорыстоваюць аднойчыны магазін, адпаведнасць за правільнасць становіцца нечыткай.

Большая адпаведнасць выклікаецца частымі, спецыфічнымі операцыямі. Лепш выкорыстоўваць addNotification, dismissNotification і clearExpiredNotifications замест простага setNotifications. Лепш выкорыстоўваць signIn, signOut і refreshSession замест універсальнага setSession. Такія операцыі маюць значэнне і дапамагаюць прадастальцу зберагчы стабільныя правілы.

Нават тады трэба, каб прадастальцы быў сфокусаваны. Універсальны дыспетчар для кожной функцыі створае глобальную взаімазалежнасць пад іншым назвам.

Багато компанентаў можу чытаць даныя ныякога карыстальніка. Лічба тых, якія магу заменіць сесію, ў значна меньшай меры. Кантэкст застаецца прыемным для керавання, калі прадастальцы контролюе жыцёвы цыкл, а іншыя компаненты взаінае дзейнуюць праз просты контракт.

Прадастальцы кантэксту можа стаць скрытым моналітам

Компаненты з вялікім размерам паводзяцца сабе ўвагу за дапамогою дужоўгіх файлаў. Адпаведныя прадастальнікі застаюцца тыхасцяй пра дужэ дзьвіг.

Структура можа выглядаць модульнаю — з малымі компанентамі і хукамі — пры чым аднаму прадастальніку належыць стан прыкладнення, запыты да сеткі, функцыя зберагчэння дадзеных, запускаваныя браузерам супэрвізоры, права, паведамленні, модальныя вікна і вырахоўваныя значэння. Файлы компанентаў застаюцца короткімі, таму што прадастальнік берэ на сябе задачу коордынацыі.

Гэта все равно моналіт; ён проста выкананае некалькі JSX-кода.

Прадастальнік можа змяніцца з несувязаных прычын. Правіла паведамленняў, трэбованні до тэмы, змены сесіі і алгорытмы работы модальных вікнаў усе зменяюць той самы модуль. Кожны корыстнік завісіць ад яго стабільнасці. Тэсты стаюць болей размаўнымі, таму што операцыі взаімаюцца праз спакойны стан. Выконавыя характарыстыкі падпадаюць, калі абнаўленні распространяюцца. Рэфакторынг вымушвае расплутаць заўважэнняя, якія ўжо включаныя ў значэнне, якое вікорыстоўваецца всюды.

Рашчын не ў значэнні бесканцовага вярстывання рады ўсамоцэлі. Вярстыванне ёсць допустым, калі кожны прадаўцы мае чыста вялікую адпаведальнасць. Калекца сфармаваных прадаўцоў зазвычай ёсць яснейшая, чым адна аб’ект, якая прэтвараецца, што дзеліць аднаковы цыкл жыцця.

Таксонамія таксама мае значэнне. Кантэкст, які патрэбны адной стазе, павінен абгружаць той паддрэв, а не всю прыкладку. Скарочаная таксонамія скарочвае як залежнасці, так і масштаб апдэйтаў.

Глобальная доступнасць должна быць адзержаная, а не стандартны варыянт для некамфортных элементаў.

Кантэкст чырпае максімум калі рашчынае тыя проблемы, якія ён насправдзе рашчынае

Кантэкст становіцца выключным, калі паддрэв дзейсна дзеліць аднаковую залежнасць ад сярэды чы ўстойчывую проблему.

Тэмы падыходзяць, таму што багато наследнікаў пацярпляюць аднойчы той самы варыянт прыказу. Локалізацыя падыходзяць, таму што фарматаванне і пераклад прыменяюцца шырока. Спяльны кліент API, сераўнікацыйная асяроддзе, дыяпазон формы або адзін рабочы працэс таксама можу належаць туды, калі кожны корыстнік знаходзіцца ўнутрь адной межы.

Значэнне не павінна быць статычным. Яго цярпець павінен быць адносным, а таксама павінна існаваць схема апдэйта, якая падходзіць корыстнікам.

Якша спраектаваны Кантэкст адпавядае на запітанні: у якой асяроддзі работае гэты паддрэв, якія залежнасці дзелююць гэтыя компаненты і да чаго являе сабой адзін рабочы працэс?

Некаляк спраектаваны Кантэкст адпавядае на запітанні: якія значэнні было клопатна перадаваць як параметры? Такое запітанне прыводзіць да нерэлевантнага статаусу, шырокіх поверхняў апдэйта, супакрытых залежнасцяў і прымітных канстантаў. Структура знікае, а власнасць стае важкай для разумэння.

Перад тым, як дадзіць Кантэкст, запытайцеся, чы розумны паддрэс выканаляе той жа значэнне, чы корыстувальнікі маюць адноны жыцёвы цыкл, як часта зміняецца значэнне, і чы прадастаўшы можа опублікаваць сувора і стабільнае кантракт. Таксама запытайцеся, якія проблэмы будзе маскаваць Кантэкст. Неправільна розташованасць статаусу, відсутнеча меж функцый, слабка складовасць, кэшаванне статаусу сервера або нез’ясованны працэс віканання не будуць выправлены простым адзінам доступам.

Кантэкст павінен распадзіць рашэнні, а не ухілявацца ад іх

Большасць няправільнага выкарыстоўвання не выходзіць з няправільнага разумеўня API. Яна выходзіць з негайнага полегчэння. Ланцуг пропаўляецца. Компоненты прабываюць да доступу. Функцыя выкідаецца без перарганізавання дрэва. Код сёньдзя ўжо легчы да напісання.

Косцы вырастаюць, калі доступ перакроўляе права на власнасць. Нэзвязаныя ціклы жыцця выкарыстоўваюць аднаго прадаўцу. Корыстувачы перзапускаюць працэсы з-за змян, якіх не бачаюць. Компаненты функцый залежная ад закрытых сэраў. Прадаўцы паступова ператвараюцца ў імпровізаваныя хранілні, кэшы запітоў і двухвыконавыя механізмы, якія ніколі не атрымалі чыстаўкавага модэлю.

Называць Context слабай бібліятэкай стану — значыць не разумець сутнасі. Ён ніколі не прэтэндаваў на тое, каб візначаць керуванне станам; ён проста перадае значэння па дрэве.

Дыяграма праектавання все рава должна адпаведзаць на пытанні: што прэдставляе гэта значэння, які модуль яго володзіць, хто мае право яго змяніць, як часта выконваюцца абнаўленні і якія корыстувачы насправды ўжоўляюць яго.

Context становіць ся найэфектывнейшым пасля таго, як гэтыя рашэнні ужо ўжо з’явіліся.