作为一个前后端分离的应用,页面展示的数据应该是单独通过 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
赋值。