使用 NextJS 对 Class 组件和 getInitialProps 进行 SSR,render 方法有未定义的数据

Using NextJS to do SSR with Class Components and getInitialProps, render method has undefined data

我是 JavaScript/React/NextJS 的新手。我已经编写了一个 React 应用程序,现在我正在尝试对其进行转换,以便所有内容都呈现在服务器上。

我学习了 https://nextjs.org/learn/basics/getting-started 上的教程,然后尝试将这些知识应用到我的应用程序中。

我的应用程序有以下要求

我不清楚如何在 "getInitialProps" 中调用我的第 3 方库中的异步方法和 return 数据。我尝试的任何方法都不起作用,谷歌搜索也无济于事。

我的项目结构是

- components
     |- header.js
     |- footer.js
     |- layout.js
- pages
     |- index.js
     |- article
          |- [id].js
- scripts
     |- utils.js

index.js 只呈现 2 篇文章的 2 个链接

export default function Index() {
     return (
        <div>
            <Link href="/article/[id]" as={`/article/1`}>
                <a>Article 1</a>
            </Link>
            <Link href="/article/[id]" as={`/article/2`}>
                <a>Article 2</a>
            </Link>
        </div>
    );
} 

utils.js 有调用第三方库方法的util方法

export function getDataFromThirdPartyLib(articleId) { 
    return thirdPartyLib.getMyData({
        "articleId" : articleId,
    }).then(function (item) {  
        return item;
   });
 }

文章/[id].js 有

 function getData(articleId){
     console.log("getData")
     getDataFromThirdPartyLib(articleId)
        .then((item) => {
            console.log("got data")
            return {
                item: item
            }
        });
 } 

 class ArticleDetails extends React.Component {

     static async getInitialProps(ctx) {
         const data = await getData(articleId);
         // I also tried the following
         // const data = getData(articleId);

         return{
             data : data 
         }
     }

     render() {
         console.log("IN RENDER")
         console.log("this.props.data") // THIS IS UNDEFINED
         // my HTML
     }
  }

问题

控制台日志记录显示数据在 render() 中始终未定义。我可以从获取数据和获取数据中看到我的日志记录,但是这些渲染是在我的渲染日志记录之后呈现的,因此一旦获取数据,渲染就不会刷新。

不同的尝试 1

我试过在我的组件定义中使用 "getData"(相对于它的外部),但这总是失败,因为它说 "getData" 不是一个函数。

 class ArticleDetails extends React.Component {

     static async getInitialProps(ctx) {
         const data = await getData(articleId); // FAILS AS SAYS getData is not a function

         return{
             data : data 
         }
     }

     getData(articleId){
         console.log("getData")
         getDataFromThirdPartyLib(articleId)
            .then((item) => {
                return {
                    item: item
                }
            });
     } 

     render() {
         console.log("IN RENDER")
         console.log(this.props.data) // THIS IS UNDEFINED
         // my HTML
     }
  }

不同的尝试 2

我尝试直接在 "getInitialProps" 中使用 "getData" 中的逻辑,但这也不起作用,因为它说 getInitialProps 必须 return 一个对象。

 class ArticleDetails extends React.Component {

     static async getInitialProps(ctx) {
          getDataFromThirdPartyLib(articleId)
            .then((item) => {
                return {
                    data: data
                }
          });
     }

     render() {
         console.log("IN RENDER")
         console.log(this.props.data) // THIS IS UNDEFINED
         // my HTML
     }
  }

工作版本 - 但不是 SSR

我能让它工作的唯一方法是像 React 应用程序中的 class 组件一样编写它。但我相信 "componentDidMount" 不是在服务器上调用的,而是在客户端调用的。所以这让我试图让所有内容都呈现在服务器中的尝试失败了。

class ArticleDetails  extends React.Component {

    state = {
        item: null,


    componentDidMount() {
        this.getData();
    }


    getData(articleId){
         console.log("getData")
         getDataFromThirdPartyLib(articleId)
            .then((item) => {
                self.setState({                
                    item: item
                }
            });
    } 

    render() {
         console.log("IN RENDER")
         console.log(this.state.item) // THIS HAS A VALUE
         // my HTML
    }    

}

Steve Holgado 提供的解决方案

问题是我的 "getData" 方法没有 return 像史蒂夫所说的那样承诺。

然而,我的 "getData" 方法比我最初在这个 post 中输入的要复杂一些,这就是为什么当我第一次尝试 Steve 的解决方案时它不起作用的原因。

我的 getData 嵌套了两个承诺。如果我将 return 放在 BOTH promises 上,它会完美运行。

function getData(articleId){
     return getDataFromThirdPartyLib(articleId)
        .then((item) => {

             return getSecondBitOfDataFromThirdPartyLib(item)
                .then((extraInfo) => {
                    return {
                        item: item,
                        extraInfo : extraInfo
                    }
                });

            return {
                item: item
            }
        });
}  

您需要 return getDataarticle/[id].js 中的承诺:

function getData(articleId){
  // return promise here
  return getDataFromThirdPartyLib(articleId)
    .then((item) => {
      return {
        item: item
      }
    });
}

...否则 undefined 被隐式 returned。

另外,你从哪里得到 articleId

它应该来自 url 吗?

static async getInitialProps(ctx) {
  const articleId = ctx.query.id;
  const data = await getData(articleId);

  return {
    data: data 
  }
}

希望这对您有所帮助。