【问题标题】:Access data from getServerSideProps in custom document Next.js从自定义文档 Next.js 中的 getServerSideProps 访问数据
【发布时间】:2021-09-29 21:59:04
【问题描述】:

我正在使用 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() 传递?

【问题讨论】:

标签: next.js


【解决方案1】:

在加载应用程序之前,这是一种将页面的 getServerSideProps() 数据获取到 _document.js 的巧妙方法。

所以,正如我所提到的,您可以使用预渲染的 html 来做一些时髦的事情,以使用 getServerSideProps() 数据。这是一个 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

由于这两个数据似乎在某种程度上可以访问,我希望有更官方的方法来做到这一点?

【讨论】:

    猜你喜欢
    • 2023-02-12
    • 2021-09-26
    • 2021-04-23
    • 2020-10-14
    • 2021-11-02
    • 2020-12-13
    • 2022-01-06
    相关资源
    最近更新 更多