#reactjs
Вопрос:
Мне поручено поддерживать несколько комплектов компонентов, применяя при этом единую систему проектирования. Чтобы помочь мне в этом, я реализовал a ThemeControllerProvider
, который предоставляет общий объект темы в Context
моих реальных поставщиках ThemeProviderA
тем и ThemeProviderB
.
Это означает, что приложение пользователя будет настроено примерно так.
<ThemeControllerProvider mode="dark">
<ThemeProviderA>
<ThemeProviderB>
<App/>
</ThemeProviderB>
</ThemeProviderA>
</ThemeControllerProvider>
Это работает нормально, но я хотел бы улучшить опыт разработчиков. Я хочу, чтобы разработчики не беспокоились о контроллере.
<ThemeProviderA>
<ThemeProviderB>
<App/>
</ThemeProviderB>
</ThemeProviderA>
Или когда они используют только один комплект компонентов…
<ThemeProviderA>
<App/>
</ThemeProviderA>
В моем ThemeControllerProvider
есть редуктор Context
, и мне удалось, чтобы каждый поставщик тем определял, присутствует ли контроллер или нет, проверяя, является ли редуктор нулевым или нет, но я не понял, что делать с этой информацией. Нижестоящим компонентам требуется controller.state.theme
поддержка, но она не существует, когда comp инициализируется без уже существующего поставщика.
// ThemeProviderA.jsx
const controller = useThemeController()
if (controller === null) {
return (
<ThemeControllerProvider>
<ThemeProviderA theme={???}>
{children}
</ThemeProviderA>
<ThemeControllerProvider>
)
} else {
return (
<ThemeProviderA theme={controller.state.theme}>
{children}
</ThemeProviderA>
)
}
Есть ли шаблон, который я могу реализовать, в котором поставщики тем могут автоматически обнаруживать отсутствие a ThemeControllerProvider
и автоматически вводить его? А также, если поставщики тем вложены, мне нужен только поставщик высшего порядка для внедрения контроллера.
Ответ №1:
ладно, это очень интересная проблема.
Предположим, что вы ThemeControllerProvider
также являетесь поставщиком контекста. Я могу сначала обдумать эту идею,
const a = useContext(Context)
a
Это не вызвало бы ошибок без зарегистрированного поставщика в качестве родителя. почему?
Context = React.createContext(defaultContextValue)
Если поставщик не зарегистрирован, значение a
будет defaultContextValue
равно значению . В вашем случае мы можем установить значение по умолчанию пустым theme
или каким-либо другим.
const defaultContextValue = { theme: ... }
реализация
Конечно, я предполагаю, что ваш контроллер-это контекст.
const ThemeControllerContext = React.createContext({ theme: null })
Остальная часть вашего кода все равно должна работать с этим изменением.
if (controller === null) {
return (
<ThemeControllerContext.Provider value={theme}>
<ThemeProviderA theme={???}>
{children}
</ThemeProviderA>
<ThemeControllerContext>
)
} else {
return (
<ThemeProviderA theme={controller.state.theme}>
{children}
</ThemeProviderA>
)
}
прочитайте материал
https://javascript.plainenglish.io/react-context-is-a-global-variable-b4b049812028
Вы можете найти свой случай, отмеченный случаем D, в приведенной выше статье.