Моя установка следующая. У меня есть компонент макета, в который я добавляю компонент навигации и дочерние элементы. Я оборачиваю их своим провайдером вот так
AppLayout.js
<Layout>
<Navigation/>
<main>
{children}
</main>
</Layout>
Теперь компонент <Navigation/>
имеет доступ к данным, возвращаемым React.useContext(ContextProvider)
.
Однако дочерний компонент Layout - нет! Если я попытаюсь console.info(state)
в компоненте <Navigation/>
, я верну фактические данные, как и ожидалось.
Но когда у меня есть дочерний компонент, подобный этому:
Child.js
<AppLayout>
<div>Some content</div>
</AppLayout>
Состояние всегда неопределенно. Единственный способ решить эту проблему — обернуть Provider вокруг компонента в файле _app.js
. Кто-нибудь знает, как решить эту проблему, не оборачивая провайдера в файл <Component/>
from _app.js
?
Это невозможно.
Каждый компонент, который должен иметь доступ к одному контексту, ДОЛЖЕН быть потомком ОДНОГО ОДНОГО поставщика контекста.
Если вы поместите поставщика контекста внутрь компонента-оболочки, и этот компонент-оболочка используется в нескольких разных позициях, каждый экземпляр будет иметь отдельный поставщик контекста, который является другим состоянием. Это просто не работает.
Если вы не хотите, чтобы ваш поставщик контекста находился в _app.js, вы можете поместить его в любой дочерний компонент, но все же каждый компонент, который хочет использовать состояние, должен быть потомком поставщика контекста.
например.:
<App>
<NoDoesNotHaveStore />
<ContextProvider store = { myStore }>
<YesDoesHaveStore />
<YesAlsoDoesHaveStore />
</ContextProvider>
</App>
Вы можете обернуть поставщика контекста:
const SomeWrapper = function(props){
return <ContextProvider store = { myStore }>
{ props.children }
</ContextProvider>;
};
<App>
<NoDoesNotHaveStore />
<SomeWrapper>
<YesDoesHaveStore />
<YesAlsoDoesHaveStore />
</SomeWrapper>
<NoStoreAgain />
</App>
Но не несколько раз:
const SomeWrapper = function(props){
return <ContextProvider store = { myStore }>
{ props.children }
</ContextProvider>;
};
<App>
<SomeWrapper>
<HasStoreA />
</SomeWrapper>
<SomeWrapper>
<HasDifferentStoreB />
</SomeWrapper>
</App>
Также обратите внимание, что в Next.js при определенных обстоятельствах хранилище может отличаться на стороне сервера и на стороне клиента или при первом рендеринге и при нажатии на ссылку Next-Link.