Контекстный API в целом
Из комментариев кажется, что потенциальная проблема заключается в том, что вы не визуализируете <Login />
как дочерний элемент <GlobalContextProvider />
. Когда вы используете получателя контекста, либо в качестве ловушки, либо в качестве функции, где-то в дереве компонентов должен быть соответствующий поставщик в качестве родительского элемента.
Например, они не будут работать:
<div>
<h1>Please log in!</h1>
<Login />
</div>
<React.Fragment>
<GlobalContextProvider />
<Login />
</React.Fragment>
, поскольку в обоих из них компонент Login является либо родным поставщиком поставщика контекста, либо поставщик полностью отсутствует.
Это, однако, будет работать:
<React.Fragment>
<GlobalContextProvider>
<Login />
</GlobalContextProvider>
</React.Fragment>
, поскольку компонент Login является дочерним по отношению к GlobalContextProvider.
Относится к Gatsby
Эта концепция верна независимо от того, какую библиотеку или инфраструктуру вы используете для создания своего приложение. В частности, в Gatsby есть небольшая работа, которую вы должны выполнить, чтобы заставить это работать на уровне страницы, но это возможно.
Допустим, у вас есть определенный файл Layout.jsx и следующая страница:
const Index = () => (
<Layout>
<h1>{something that uses context}</h1>
</Layout>
)
У вас есть 2 варианта:
- Более простой вариант - извлечь
h1
в его собственный файл компонента. Затем вы можете поместить GlobalContextProvider
в Layout
и поместить контекстного потребителя в новый компонент. Это сработает, потому что h1 визуализируется как дочерний элемент макета. - Это сделать некоторую перестановку.
Возможно, вы захотите поместить провайдера в макет и попробовать потреблять его на странице. Вы можете подумать, что это сработает, потому что h1 по-прежнему отображается как дочерний элемент макета, верно? Это правильно, но контекст не используется h1. Контекст визуализируется h1, а потребляется Index, который является родителем <Layout>
. Использование его на уровне страницы возможно, но вам нужно создать другой компонент (IndexContent
или что-то подобное), использовать ваш контекст в там и визуализировать , что как ребенок макета. В качестве примера (с кратким описанием импорта):
const Layout = ({children}) => (
<GlobalContextProvider>
{children}
</GlobalContextProvider>
);
const IndexContent = () => {
const {text} = useContext(GlobalStateContext);
return <h1>{text}</h1>;
}
const Index = () => (
<Layout>
<IndexContent />
</Layout>
);