【发布时间】:2020-11-06 10:57:39
【问题描述】:
我正在尝试从我的模型中获取一些数据,使用 GraphQL 以便通过本地化语言动态预填充导航栏:
export async function getPageTitleBySlug(slug) {
const data = await fetchAPI(
`query PageTitleBySlug($where: JSON){
pages(where: $where) {
title_en
title {
title_es
title_tr
}
}
}`,
{
variables: {
where: { slug },
},
}
)
return data
}
很简单。
我从 navbar 组件调用这个函数:
export async function getLocalizedTitle(slug) {
const data = await getPageTitleBySlug(slug)
return { ...data?.pages[0] }
}
这个函数在组件内部调用:
const [labels, setLabels] = useState(links.map(({ label }) => ({ [label]: "" })))
useEffect(() => {
links.map(async ({ label }) => {
const { title, title_en } = await getLocalizedTitle(label)
const localizedTitle =
title[
Object.keys(title).find(
(content) => content.split("_")[1] == i18n.language
)
] || title_en
setLabels({ [label]: localizedTitle })
})
}, [i18n.language])
它确实有效,因为每次我更改本地语言时,都会调用此效果。
我的想法是从以下字典中获取值:
{links.map(({ key, href, label }) => (
<MenuItem key={key}>
<Link href={href}>
<a></a>
</Link>
</MenuItem>
))}
很容易意识到问题出在 fetch 中,但它只是在我从组件调用 fetch 时发生。
我尝试在渲染页面之前填充数据,但 getInitialProps 和 setStaticProps 仅适用于页面。
更新 按照我在thread 中找到的指示,我进行了下一次更新:
FolioApp.getInitialProps = async (appContext) => {
const appProps = await App.getInitialProps(appContext)
// TODO: Here at beginning is undefined, so, i'm getting errors in console, it should be a defaultProp, but how?
let navProps = {}
menu_links.map(async ({ label }) => {
const { title, title_en } = await getLocalizedTitle(label)
navProps[label] = { title, title_en }
})
const defaultProps = appContext.Component.defaultProps
return {
...appProps,
navProps,
pageProps: {
namespacesRequired: [
...(appProps.pageProps.namespacesRequired || []),
...(defaultProps?.i18nNamespaces || []),
],
},
}
}
我的目标是获得一个字典,其中包含标题(一个对象)和数组中所有链接的 title_en 值,调用该函数一次。
后来,我将此字典作为默认属性传递给_app 组件:
const FolioApp = ({ Component, pageProps, navProps }) => {
useEffect(() => {
// Remove the server-side injected CSS.
const jssStyle = document.querySelector("#jss-server-side")
if (jssStyle) {
jssStyle.parentElement.removeChild(jssStyle)
}
}, [])
return (
<>
<Meta />
<DefaultSeo
{...DefaultSEO}
additionalMetaTags={[
{
name: "msapplication-TileColor",
content: CMS_TILE_COLOR,
},
{
name: "msapplication-config",
content: "/favicon/browserconfig.xml",
},
]}
/>
{/* TODO: Add a proper theme */}
<ThemeProvider theme={theme}>
<CssBaseline />
<Nav navLinks={navProps} />
<Component {...pageProps} />
<Footer navLinks={navProps} />
</ThemeProvider>
</>
)
}
navLinks 是属性,我将它传递给footer 和nav。当页面确实存在时,它大部分时间都可以工作;但是,当我们收到 404 错误页面甚至在索引中时,它不起作用:
我在错误或索引页面中收到一个空的navLinks。为什么?
更新:
现在,我尝试使用Promise.all 解决它,以便在将所有获取的数据加入一次之前将其传递给道具:
await Promise.all(
menu_links.map(async ({ label }) => {
const { title, title_en } = await getLocalizedTitle(label)
navProps[label] = { title, title_en }
})
)
它确实有效,但我不太喜欢这个解决方案。
我搜索了cms-strapi 示例,发现它从一次提取中获取全部数据,这是最好的,因为getInitialProps 只执行一次,并且比为每种不同类型的所需数据单独提取执行得更好.
因此,感谢 strapi documentation,我更改了我的获取功能,我重新制作了该功能以获取所有数据,然后将其传递给属性。
它解决了渲染菜单的问题,但它没有解决我使用Promise.all 和获取解决方案时遇到的下一个问题:
如您所见,每次我进入索引页面时,都会遇到该错误,这是因为它使用localhost:3000/undefined/graphql 获取而不是localhost:1337/graphql,默认情况下设置为process.env.API_URL,如process.env.API_URL;当我从每个页面重定向到 Home(index) 时,就会发生这种情况,有时会出现 404 或 500 错误。
我不是很明白。
我该如何处理?
谢谢。
【问题讨论】:
标签: javascript reactjs graphql next.js fetch-api