NextJS getServerSideProps 将数据传递给页面类

时间:2021-02-09 22:53:08

标签: javascript reactjs next.js

我知道这可能已经被问到了,但我现在不知道该怎么做。 我不是一个(非常)有经验的 javascript 或 NextJS 开发人员。

我的问题(1): 我得到了方法:export const getServerSideProps: GetServerSideProps = async () => {} 实现以从集成 API(来自 NextJS 的 pages/api)获取一些数据。代码本身可能写得不好(或更糟),但它有效。 (至少现在是这样)

export const getServerSideProps: GetServerSideProps = async () => {
    try {
        // get userID
        await fetch("http://localhost:32147/api/v1/user/get?requestedField=userID&fieldName=username&fieldValue=<value removed>").then(
            (userIDResponse: Response): any => {
                // get userID as json
                userIDResponse.json().then((userIDResult: Response): any => {
                    // get messages
                    fetch(
                        "http://localhost:32147/api/v1/message/get?requestedField=*&fieldName=userID&fieldValue=" +
                            JSON.stringify(userIDResult[0].userID)
                    ).then((messageResponse: Response): any => {
                        // get messages as json
                        messageResponse.json().then((messageResult) => {
                            return {
                                props: { messages: messageResult },
                                {/* marker1 */}
                            }
                        })
                    })
                })
            }
        )
    } catch (error) {
        console.log(error)
    }
}

需要说明的是,此方法有效,数据获取有效,但前提是我在 ma​​rker1
访问它 我返回道具的那一部分:

return {
props: { messages: messageResult },
}

我不能这样做,因为 nextjs 会因为 getServerSideProps() 没有返回任何东西而崩溃。 我试图将最终数据存储到一个变量中,该变量是我在此方法的第一行声明的,但它最终一直是空的。

我该如何解决这个问题?

我的问题(2):如果我在此方法的末尾设置了一个手动值进行测试,它不会传递给主页面类 (index.tsx) 我可以使用 this.props.<prop name> 访问它,在这种情况下:this.props.messages,对吗?

整个index.tsx

import React, { Component } from "react"
import { GetServerSideProps } from "next"
import Router from "next/router"
import Head from "next/head"

import Navbar from "../lib/Navbar"
import MessagesModal from "../lib/MessagesModal"

export const getServerSideProps: GetServerSideProps = async () => {
    try {
        // get userID
        await fetch("http://localhost:32147/api/v1/user/get?requestedField=userID&fieldName=username&fieldValue=<value removed>").then(
            (userIDResponse: Response): any => {
                // get userID as json
                userIDResponse.json().then((userIDResult: Response): any => {
                    // get messages
                    fetch(
                        "http://localhost:32147/api/v1/message/get?requestedField=*&fieldName=userID&fieldValue=" +
                            JSON.stringify(userIDResult[0].userID)
                    ).then((messageResponse: Response): any => {
                        // get messages as json
                        messageResponse.json().then((messageResult) => {
                            return {
                                props: { messages: messageResult },
                            }
                        })
                    })
                })
            }
        )
    } catch (error) {
        console.log(error)
    }
}

interface HomeProps {
    messages?: []
}

export default class Home extends Component<HomeProps> {
    constructor(props) {
        super(props)
    }

    state = {
        messagesModal: false,
        messages: [],
    }

    // triggers logout
    triggerLogOut(): void {}

    render(): JSX.Element {
        return (
            <>
                <Head>
                    <title>OneDrive Event Connector</title>
                </Head>
                <Navbar
                    ItemClickCallback={(callbackItem: string): void => {
                        if (callbackItem === "messages") {
                            this.setState({ messageModal: !this.state.messageModal })
                        } else if (callbackItem === "log_out") {
                            this.triggerLogOut()
                        } else {
                            Router.push("/" + callbackItem)
                        }
                    }}
                />
                <div className="app-content"></div>
                <MessagesModal
                    messages={this.props.messages}
                    isOpen={this.state.messagesModal}
                    toggleModal={() => {
                        this.setState({ messageModal: !this.state.messagesModal })
                    }}
                />
            </>
        )
    }
}

这只是一个让我练习和学习的“有趣”项目。
如果有人能给我一个提示,告诉我我的问题/错误是什么,那就太好了...

谢谢。

亲切的问候
奥利弗

1 个答案:

答案 0 :(得分:0)

<块引用>

我不能这样做,因为 nextjs 会因为 getServerSideProps() 没有返回任何东西而崩溃。

确切地说 - 在您的代码中,您返回的是承诺链中的值 - 您需要确保每一步都返回值

这是一个工作示例 - 与交换 API 类似的流程 - 帮助您了解如何返回某些内容,从链式承诺的内部返回

export const getServerSideProps: GetServerSideProps = async () => {
    try {
        // initial fetch
        const result = await fetch("https://jsonplaceholder.typicode.com/todos/1")
            .then((todosResponse: Response): any => {
                return todosResponse.json().then((todo) => {
                    // fetch something more
                    return fetch(
                        "https://jsonplaceholder.typicode.com/users/" + todo.userId
                    ).then((userResponse: Response): any => userResponse.json());
            })
        })
        return {
            props: { messages: result },
        }
    } catch (error) {
        console.log(error)
    }
}

我的建议也是阅读更多关于 JS 世界中的 promises/async await

<块引用>

我的问题(2) 我可以使用 this.props. 访问它,在这种情况下:this.props.messages,对吗?

是的,没错

interface HomeProps {
    messages?: []
}
export default class Home extends Component<HomeProps> {
    constructor(props) {
        super(props)
    }
    render() {
        return (
            <>
                {JSON.stringify(this.props.messages)}
            </>
        )
    }
}