У меня есть перехват useGetFooId
, который пытается получить Foo ID из магазина Redux с запасной логикой:
Это выглядит примерно так:
const useGetFooId = () => {
const { fooId: fooIdFromSelector } = useSelector(uiSelector);
const fooIdFromLessReliablePlace = getFooIdFromLessReliablePlace();
const fooIdFromVeryUnreliablePlace = getVeryUnreliableFooId();
return fooIdFromSelector
?? fooIdFromLessReliablePlace
?? fooIdFromVeryUnreliablePlace
?? null;
}
Теперь я хочу сделать useGetFooId
безопасным для звонков за пределами провайдера Redux. (Идентификатор Foo имеет отношение к некоторой логике отображения в компоненте границы ошибки в корне приложения). Прямо сейчас, если он вызывается из-за пределов провайдера, он получает следующую ошибку: Cannot read properties of null (reading 'store')
.
По сути, желаемое поведение таково: если useGetFooId
вызывается из-за пределов селектора, он использует ту же логику возврата, как если бы fooId
не был определен в селекторе (поэтому он должен вернуть fooIdFromLessReliablePlace ?? fooIdFromVeryUnreliablePlace ?? null
).
Есть ли поддерживаемый способ условного доступа к хранилищу Redux, только если доступен поставщик или что-то в этом роде? Я изначально думал обернуть это в try/catch, но кажется, что это нарушает правила хуков: https://github.com/facebook/react/issues/16026
🤔 А знаете ли вы, что...
JavaScript позволяет создавать динамические и интерактивные веб-приложения.
Перепишите свой собственный способ подписки на изменения из хранилища, используя объект магазина напрямую вместо хука useSelector
, который нельзя вызывать условно, например нельзя назвать условно через try/catch
.
Смотрите магазин.подписывайтесь .
Используйте крючок useEffect
, чтобы создать экземпляр прослушивателя, который может выбрать текущее значение fooId
из хранилища и сохранить его в локальном состоянии React. Вы можете окружить логику подписки магазина try/catch
.
import { store } from '../path/to/store';
const useGetFooId = () => {
const [fooIdFromSelector, setFooIdFromSelector] = React.useState(null);
React.useEffect(() => {
try {
const unsubscribe = store.subscribe(() => {
const { fooId } = uiSelector(store.getState());
setFooIdFromSelector(fooId);
});
return unsubscribe;
} catch(error) {
// some error happened during the store subscription
// handle/log/ignore/etc, it's up to you
}
}, []);
const fooIdFromLessReliablePlace = getFooIdFromLessReliablePlace();
const fooIdFromVeryUnreliablePlace = getVeryUnreliableFooId();
return fooIdFromSelector
?? fooIdFromLessReliablePlace
?? fooIdFromVeryUnreliablePlace
?? null;
};
Вам нужна только логика вне провайдера, а не селектора, потому что:
Желаемое поведение в основном следующее: если useGetFooId вызывается из вне селектора он использует ту же логику возврата, что и fooId был не определен в селекторе (поэтому он должен вернуть fooIdFromLessReliablePlace ?? fooIdFromVeryUnreliablePlace ?? нулевой).
Создайте функцию с именем getFooId
, которая при необходимости получает id
(id
также может быть undefined
, и используйте ее в пользовательском хуке и непосредственно на границе ошибки (id
будет undefined
):
// only call other functions if the previous value is `null` or `undefined`
const getFooId = id => id
?? getFooIdFromLessReliablePlace()
?? getVeryUnreliableFooId()
?? null;
const useGetFooId = () => {
const { fooId: fooIdFromSelector } = useSelector(uiSelector);
return getFooId(fooIdFromSelector);
}