Итак, в React правила хуков говорят, что хуки нельзя вызывать вне функциональных компонентов.
Мое затруднительное положение: мне нужно инициализировать состояние в моем createContext, используя перехватчик для SchedulesProvider. Состояние представляет собой динамическую дату, например, через два дня от текущей даты. Хуки нельзя вызывать вне функциональных компонентов. createContext нельзя вызвать внутри компонента поставщика, поскольку его необходимо экспортировать и использовать вне SchedulesProvider.
Что я пробовал
const utils = useUtils(); //useUtils is a hook from a date library
export const ScheduleContext = createContext({
scheduleStartDate: utils.date().add(2, "days"), //using the hook here
...
});
Мой провайдер пытается передать состояние вот так...
const { scheduleStartDate } = useContext(ScheduleContext);
<ScheduleContext.Provider
value = {{
scheduleStartDate: scheduleStartDate,
}}
>
{children}
</ScheduleContext.Provider>
Я получаю сообщение об ошибке: Неверный вызов перехватчика. Хуки можно вызывать только внутри тела функционального компонента.
scheduleStartDate
или scheduleEndDate
? Это смущает
Вероятно, вам не нужно значение по умолчанию для вашего контекста. Значение по умолчанию используется только в том случае, если выше в дереве компонентов нет ScheduledContext.Provider
, и вы можете расположить свои компоненты так, чтобы этого никогда не происходило.
Если вам не нужно значение по умолчанию, вы можете подождать, пока провайдер не будет вызывать useUtils
. Например:
export const ScheduleContext = createContext(null);
// ...
const MyProvider = ({ children }) => {
const utils = useUtils();
return (
<ScheduleContext.Provider value = {{
scheduledStartDate: utils.date().add(2, "days")
}}>
{children}
</ScheduledContext.Provider>
)
}
Как при такой настройке компонент, завернутый в поставщика, будет читать реквизиты? Разве им не нужно импортировать ScheduleContext и деконструировать из него реквизиты, чтобы их прочитать? Я зациклен на том, как дочерние компоненты смогут читать ScheduleStartDate.
Дочерний компонент импортирует ScheduleContext
, а затем вызывает const { scheduledStartDate } = useContext(ScheduleContext)
во время рендеринга.
Спасибо! Я слишком усложнил это и не знал, что createContext может иметь такое же значение null. Починил это.
Да, когда вы вызываете useContext(ScheduleContext)
, React будет искать в дереве компонентов ближайший <ScheduleContext.Provider>
и возвращать его значение. Единственный способ вернуть null
(или другое значение по умолчанию) — это если <ScheduleContext.Provider>
не существует. Поэтому, пока вы отображаете <ScheduleContext.Provider>
в верхней части дерева компонентов, вам никогда не придется иметь дело со значением по умолчанию.
Значение, которое вы передаете createContext()
, больше похоже на запасной вариант, когда оно используется вне иерархии вашего поставщика контекста.
Параметры
defaultValue
: значение, которое вы хотите, чтобы контекст имел, когда в дереве над компонентом, считывающим контекст, нет соответствующего поставщика контекста. Если у вас нет значимого значения по умолчанию, укажитеnull
. Значение по умолчанию предназначено как запасной вариант «последней меры». Оно статично и никогда не меняется со временем.
Вместо этого установите реальную стоимость с помощью собственного компонента поставщика.
const ScheduleContext = createContext({
scheduleStartDate: new Date(), // or literally anything really
// ...
});
// define a context provider component
const ScheduleContextProvider = ({ children }) => {
const { date } = useUtils();
const scheduleStartDate = date().add(2, 'days');
return (
<ScheduleContext.Provider value = {{ scheduleStartDate }}>
{children}
</ScheduleContext.Provider>
);
};
// this is also a very handy custom hook for your context
const useSchedule = () => useContext(ScheduleContext);
export { ScheduleContextProvider as default, useSchedule };
Я предпочитаю устанавливать реальное значение по двум причинам...
Ожидаете ли вы, что значение по умолчанию когда-либо будет использоваться? В большинстве случаев использования контекста значение по умолчанию не имеет значения, поскольку значение поступает от поставщика, а не по умолчанию. (Под «значением по умолчанию» я имею в виду объект, который вы передаете
createContext
)