网络数据的请求,是现代网页的最基本组成部分。一起看一下 nextjs
怎么实现的。
nextjs
为 React.Component
组件提供了 getInitialProps
钩子函数。这里我们新建一个文件 req.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React, { Component } from 'react';
export default class extends Component { static async getInitialProps({ req }) { const userAgent = req ? req.headers['Accept'] : navigator.Accept; return { userAgent }; }
render() { return ( <div> Hello World {this.props.userAgent} </div> ); } }
|
启动项目,访问 localhost:3000/req
,页面上会输出我们本次请求的 user-agent(用户代理)
信息。
回过头来看一下代码,使用了 async
ES7 关键字,表示 getInitialProps
异步执行,这样可以加快服务端的渲染速度。
我们可以修改 req.js
代码如下,看一下组件的挂载周期。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import React, { Component } from 'react';
export default class extends Component { static async getInitialProps({ req }) { console.log('getInitialProps'); const userAgent = req ? req.headers['user-agent'] : navigator.userAgent; return { userAgent }; }
constructor(props) { super(props); console.log('constructor'); }
componentWillMount() { console.log('componentWillMount'); }
componentDidMount() { console.log('componentDidMount'); }
render() { console.log('render'); return ( <div> Hello World {this.props.userAgent} </div> ); } }
|
查看浏览器控制台:
1 2 3 4
| constructor componentWillMount render componentDidMount
|
查看服务器控制台:
1 2 3 4
| getInitialProps constructor componentWillMount render
|
浏览器控制台并没有打印出 getInitialProps
钩子方法中的输出内容。
事实上,对于初始页面加载,getInitialProps
将仅在服务器上执行。getInitialProps
只有在通过Link组件导航到不同的路由或使用路由API 时,才能在客户端上执行。
getInitialProps
只能在 pages/
下的组件中使用,不能再子组件中使用。
可见,如果我们要进行接口数据的请求,可以放在 getInitialProps
服务器端执行。
下面是一个使用无状态方法实现 React 组件的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from 'react';
import fetch from 'isomorphic-fetch';
const Page = ({ stars }) => ( <div> Next stars: {stars} </div> );
Page.getInitialProps = async ({ req }) => { const res = await fetch('https://api.github.com/repos/zeit/next.js'); const json = await res.json(); return { stars: json.stargazers_count }; };
export default Page;
|
getInitialProps
方法中可利用的属性:
/req?a=aa&b=bb
请求地址:
- pathname - URL 中的路径部分
/req
- query - URL 参数部分解析为对象
/req?a=aa&b=bb
=> { a: 'aa', b: 'bb' }
- asPath - 浏览器中显示的实际路径
/req?a=aa&b=bb
- req - HTTP request object (仅服务器)
- res - HTTP response object (仅服务器)
- jsonPageRes - 服务器返回对象 (仅浏览器)
- err - 渲染过程中遇到的任何错误