Next.js: Pattern: Load Initial Data

20th August 2020 at 2:19pm

Next.js 9.3 开始将 getInitialProps 置为 deprecated,因此这个文档内容已过时。参考 Next.js: Data Fetching

作为一个前后端分离的应用,页面展示的数据应该是单独通过 API 接口获取的。对于一个需要加载远程数据的页面,因为 Next.js 是带 SSR 的框架,它需要实现这几种场景:

  • 如果用户是通过其他页面跳转到本页面,则在客户端发起 AJAX 请求获取数据
  • 如果用户是直接在浏览器访问此页面,那么数据应该由服务端获取好并直接组装成 HTML 给到浏览器

因此,有别于 React 可以使用的 componentDidMount() 这种客户端的 lifecycle event 来做这件事情,Next.js 需要提供自己的机制,来确保上述两个场景都会去拉远程数据。它给出的是一个静态方法 getInitialProps官方文档)。注意点在于,由于你的拉数据代码需要同时在客户端及服务端(Node.js)跑,因此你用的拉取的 API 需要是同构的(isomorphic)。官方提供的例子使用了 isomorphic-unfetch

import React from 'react'
import fetch from 'isomorphic-unfetch'

class Page extends React.Component {
  static async getInitialProps(ctx) {
    const res = await fetch('https://api.github.com/repos/zeit/next.js')
    const json = await res.json()
    return { stars: json.stargazers_count }
  }

  render() {
    return <div>Next stars: {this.props.stars}</div>
  }
}

export default Page

这是一个用 axios 的例子:

class IndexPage extends React.Component<any, any> {
  static async getInitialProps() {
    const client = applyConverters(axios.create());
    try {
      const response = await client.get('http://127.0.0.1:8000/posts');
      return {
        things: response.data
      }
    } catch (error) {
      // Error handling
      console.log(error);
      return {
        things: []
      }
    }
  }

  constructor(props) {
    super(props);

    // Patterns from https://github.com/zeit/next.js/issues/1072#issuecomment-279014158
    this.state = props;

    // class methods are not bound by default. Bind this to methods.
    this.handleNewThing = this.handleNewThing.bind(this);
  }
}

同时看上面代码,如果你想把拉下来的数据当成 state 来用,那么你可以在 constructor 中给 this.state 赋值。