我正在使用 getServerSideProps 获取事件的详细信息。我的理解是,这些数据将在服务器上获取,然后会发生某种预渲染,然后将上下文对象传递到 _document.js。我知道 _document.js 将在每个请求上呈现,但如果存在该服务器数据,我想向我的 html 添加一个类名(以防止在执行此客户端时闪烁)。
这是我的 getServerSideProps 函数:
export async function getServerSideProps(context) {
const shortId = context.params.short_id
const event = await GETrequest({ endpoint: API_PUBLIC_EVENT({ shortId }) })
return {
props: {
event,
shortId
} // will be passed to the page component as props
}
}
当我在 _document.js 中时,我能够看到我的 getServerSideProps 的结果可用,就像我在 getInitialProps 中记录上下文时看到的那样:
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
console.log(initialProps)
// can see html that has been processed using my data
}
...
我可以想到在那个 initialProps.html 中获取我的 className 的一些hacky 解决方案,但我想知道是否有更简单的方法。
有没有一种方法可以构建它,以便我的数据在 _document.js 中更容易使用,从 getServerSideProps() 传递过来?
答案 0 :(得分:0)
这是一种在应用加载之前将您网页的 getServerSideProps()
数据导入您的 _document.js
的黑客方法。
所以,正如我所提到的,您可以使用使用 getServerSideProps() 数据的预渲染 html 做一些时髦的事情。这是一个hacky解决方案并且非常不可靠。然而,在我的情况下,我只是在我的文档中添加一个无关紧要的 className(前端带有故障安全功能),因此即使失败也一切正常。
如果您决定使用它,请务必谨慎。
这是它的工作原理:
我在页面上有一个 getServerSideProps()。在这个函数中,我获取一个事件并将其传递到我的页面组件中。在这个组件中,我添加了一个我知道将被呈现的空 div,并附加了我需要的信息。此信息来自我的 getServerSideProps()。
<div data-meta-event-theme={event?.theme?.preset}></div>
// let's say theme preset = light
然后在我的 _document.js
中,在 getInitialProps(ctx)
函数中,我首先检查这是否是服务器请求。如果不是,则跳过(否则构建将失败)。然后我检查请求是否来自适当的路由。我的路线结构类似于 /j/[shortId]
,它是唯一使用 /j/
的页面。所以在触发任何逻辑之前,我会检查以确保我们在正确的页面上。
const isInviteScreen = ctx.req.url.indexOf('/j/') > -1
如果我们在正确的页面上,那么我们可以从我们的 html 解析值,然后用它做我们想做的事。
if (isInviteScreen) {
const html = initialProps.html
// whatever you set your data to in the html
// make sure to keep the opening quote "
const key = 'data-meta-event-theme="'
// you don't have to touch this
const begin = html.indexOf(key)
const sub = html.substring(begin + key.length)
const closingQuote = sub.indexOf('"')
const value = sub.substring(0, closingQuote)
console.log(value)
// logs 'light'
}
此时,我可以将该值作为 className 附加到我的 html 中,瞧!不再闪烁。
这是一个更完整的_document.js
:
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
// Make sure this operation is on the server and has a request
if (ctx.req) {
// Make sure we're only doing this for the correct route
const isInviteScreen = ctx.req.url.indexOf('/j/') > -1
if (isInviteScreen) {
const html = initialProps.html
// Your HTML key here, make sure to keep quote
const key = 'data-meta-event-theme="'
// Don't have to touch this
const begin = html.indexOf(key)
const sub = html.substring(begin + key.length)
const closingQuote = sub.indexOf('"')
// Value that was sent from the page with getServerSideProps()
const value = sub.substring(0, closingQuote)
return {
...initialProps,
preference: { theme: value }
}
}
}
// Default return just in case
return {
...initialProps,
preference: { theme: 'light }
}
}
render() {
const theme = this.props.preference.theme
return (
<Html data-theme={theme} className={theme} lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
由于这些数据在两者之间似乎有些可访问,我希望有更正式的方法来做到这一点?