Рубрики
Без рубрики

Реагировать контекст без поставщика + usemutablesource

Этот пост был первоначально опубликован в моем личном блоге. Некоторое время назад я читал RFC из React’s … Tagged with React, WebDev, Performance, JavaScript.

Этот пост был первоначально опубликован в моем личном блог .

Некоторое время назад я читал RFC из RFC React, называемых UseMutablesource ; Это была экспериментальная особенность, которая в двух словах позволяет безопасно читать, писать и даже редактировать внешний источник (за пределами дерева компонентов React). Это особенность Бэнджера, которую я действительно за это разжигал, но в то же время экспериментально. Возможно, вы знаете, что я работаю над библиотекой государственного управления с открытым исходным кодом под названием Jotai. Эта библиотека анонсировала новую функцию, режим без поставщика. Чтобы знать, что это такое, подумайте о контексте реагирования, но не нуждается в Поставщик Компонент, это не совсем, но это дает вам идею.

Почему новый?

Да, у нас есть шаблоны и библиотеки, которые позволяют нам читать и писать из внешнего источника, но, как я уже сказал, этот позволяет вам делать вещи безопасно; больше нет разрывов.

Разрыв

Подумайте о том, чтобы разрываться как что -то вроде, если у нас есть ценность (состояние), которое A и B читают из этого, но каким -то образом в рендеринге изменяется ценность. B -компонент позже, чем Таким образом, в рендеринге значение в компоненте A составляет 0, а в более новом компоненте (B) значение составляет 1. Мы называем это разрывом; Это означает, что вы видите два разных значения в просмотре из одного точного источника. Это новая и трудно понять реализацию в одновременном режиме React; Для получения дополнительной информации см. это Анкет

Экспериментальный, почему я должен его использовать?

Итак, я подумал об этом, у нас есть два варианта:

  • Экспериментальная версия React: пряжа добавить React@экспериментальный
  • Последовательная версия UseMutablesource , вы можете скопировать вставить его из здесь

Я рекомендую второй вариант, потому что он не изменится, и пока хорошо, если у нас нет UseMutablesource В основной версии реагирования.

Контекст без поставщика

Я думаю, что мы достигли того, что привело вас сюда, но подождите, прежде чем все это, не забудьте посмотреть на мой GitHub и Twitter ; Вы увидите там классные вещи и помогите мне с моим учебным путешествием. Итак, начнем.

Некоторые из приведенных ниже кода написаны с помощью TypeScript, поэтому он будет более понятным, даже для людей, которые не знают TypeScript.

Начинать

Сначала нам нужно создать простой глобальный объект, который содержит три свойства:

 const globalStore = {
  state: { count: 0 },
  version: 0,
  listeners: new Set<() => any>()
};
  • Государство : простое значение, такое как значение контекста React
  • Версия : важная часть, которая должна меняться, когда какая -либо часть состояния меняется
  • Слушатели : Набор функций, которые мы называем им каждый раз, когда меняем часть государство , поэтому мы уведомим их об изменениях

Теперь нам нужно создать изменчивый источник из Globalstore И дайте ему версию, так что это поможет ей сэкономить новые изменения, поэтому мы собираемся получить к нему доступ к ней в GetSnapShot и подписываться ; Мы скоро поговорим об этом.

const globalStoreSource = createMutableSource(
  globalStore,
  () => globalStore.version // (store) => store.version (Optional) if you use the consistent and non-experimental version of useMutableSource
);

Теперь пришло время поговорить о GetSnapShot ; Короче говоря, это функция, которая UseMutablesource Возвращает возвращаемое значение всякий раз, когда изменение состояния.

const cache = new Map();

const getSnapshot = (store: typeof globalStore) => {
  const setState = (
    cb: (prevState: typeof store.state) => typeof store.state
  ) => {
    store.state = cb({ ...store.state });
    store.version++;
    store.listeners.forEach((listener) => listener());
  };
  if (!cache.has(store.state) || !cache.has(store)) {
    cache.clear(); // remove all the old references
    cache.set(store.state, [{ ...store.state }, setState]); 
    // we cache the result to prevent the useless re-renders
    // the key (store.state) is more consistent than the { ...store.state },
    // because this changes everytime as a new object, and it always going to create a new cache
    cache.set(store, store); // check the above if statement, if the store changed completely (reference change), we'll make a new result and new state
  }

  return cache.get(store.state); // [state, setState]
};
// later: const [state, setState] = useMutableSource(...)

Взгляните на SetState Функция, сначала мы используем CB и передайте его предыдущему состоянию, затем назначьте его возвращенное значение нашему состоянию, затем мы обновляем версию магазина и сообщаем всех слушателей о новом изменении.

Мы использовали оператор спреда ({... store.state}) Потому что мы должны клонировать значение, поэтому мы делаем новую ссылку для нового объекта состояния и отключили прямые мутации.

У нас нет слушатель Тем не менее, как мы можем добавить его? с подписаться функция, посмотрите на это:

const subscribe = (store: typeof globalStore, callback: () => any) => {
  store.listeners.add(callback);
  return () => store.listeners.delete(callback);
};

Эта функция будет вызвана UseMutablesource В Так что это проходит подписаться два параметра:

  • Магазин : который является нашим оригинальным магазином
  • обратный вызов : Это вызовет наш компонент повторно (по UseMutablesource )

Итак, когда UseMutablesource Вызывает подписку, мы собираемся добавить обратный вызов нашим слушателям. Всякий раз, когда что-то меняется в штате ( setState ), мы называем всех наших слушателей, чтобы компонент был повторно рендер. Вот как у нас есть обновленная стоимость каждый раз с UseMutablesource Анкет

Таким образом, вы можете задаться вопросом, мы удалили обратный вызов взамен, ответ таково, что когда компонент намекает, UseMutablesource позвонит subscribe () , или в другом семестре мы называем это Отписаться . Когда он будет удален, мы больше не будем называть бесполезный обратный вызов, который приведет к повторному рендерингу для необедененного (или иногда старого) компонента.

UseContext

Теперь мы достигли конечной линии, не думайте слишком много о названии, мы просто хотели имитировать версию без поставщика контекста React.

export function useContext() {
  return useMutableSource(globalStoreSource, getSnapshot, subscribe);
} // returns [state, setState]

Теперь мы можем использовать эту функцию везде, где хотим. Взгляните на этот пример, или, если хотите, вы можете пойти прямо на CodeSandbox .

function Display1() {
  const [state] = useContext();
  return 
Display1 component count: {state.count}
; } function Display2() { const [state] = useContext(); return
Display2 component count: {state.count}
; } function Changer() { const [, setState] = useContext(); return ( ); } function App() { return (
); }

Теперь, когда вы нажимаете кнопку +1, вы можете увидеть красивые изменения без каких -либо Поставщик Анкет

Я надеюсь, что вам понравилась эта статья, и не забудьте поделиться и реакции на мою статью. Если вы хотите мне что -нибудь сказать, скажите мне о Twitter или упомянуть меня где угодно, вы даже можете подписаться на мой Информационный бюллетень Анкет

  • Покрытие изображения: эксперимент, Николас Томас, Unsplash

Оригинал: “https://dev.to/aslemammad/react-context-without-provider-usemutablesource-4aph”