Этот пост был первоначально опубликован в моем личном блог .
Некоторое время назад я читал 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(); returnDisplay1 component count: {state.count}; } function Display2() { const [state] = useContext(); returnDisplay2 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”