必会的next.js自定义App和Document

前言

这篇文章将介绍Next.js中自定义App组件、Document组件以及何时须要自定义这些内容,这可能会是咱们每一个项目中都要作的事情,So,让咱们一块儿掌握它吧。javascript

Tips: 按照惯例声明,笔者也是个入门级选手,文章深度没法达到大佬级文章水平,只但愿能对各位入门级的小伙伴有所帮助。css

自定义App

首先说一下为何要自定义App,这里的App其实就是咱们平时写react时候的根组件。 1)经过重写_app.js文件,咱们能够对App组件进行重构,在App组件中加入一些项目中不变的内容,好比页面的布局;java

2)在App中保持公用的状态,这里的公用状态也能够是一些全局的css,好比咱们以前搭建环境的文章中加入的antd.cssreact

3)以及给页面传递自定义的数据,服务器

4)使用componentDidCatch自定义处理错误;antd

5)注入额外数据到页面里 (如 GraphQL 查询)app

next.js+koa2+antd环境轻松搭建 一文中,咱们曾经写过一个_app.js来引入antd的css,在这里咱们对除了引入antd.css其余事情什么都没作,引入antd.css以后,它就会在全局生效。frontend

import App from 'next/app'
import 'antd/dist/antd.css'
export default App
复制代码

如今就来对它进行一些改变koa

import App, { Container } from 'next/app'
import 'antd/dist/antd.css'

// 新增了这一段
class MyApp extends App {
    render() {
        const { Component } = this.props; 
        console.log(Component);

        return (
            <Container> <Component /> </Container>
        )
    }
}

export default MyApp
复制代码

对比这一段代码,这里从next/app中多引入了一个Container组件,并在中间从新写了一个MyApp类,继承自App,最后将其返回。在MyApp中,重写了render方法来渲染组件,其中从props中拿到的Component组件就是在访问每一个pages下的js文件时候,这些文件返回的组件。想一想也是,在写react的时候,其余组件要显示也是要包裹在最外层的App组件中的,这里是同样的道理。 值得注意的是,这里的MyApp组件返回Component时候最外层要使用Comtainer组件进行包裹。咱们能够顺手打印出Component,看看究竟是不是向咱们所说的同样。 异步

重写getInitialProps

不过如今并不算完成,咱们连App本来的功能还没实现完整:在当前组件中,咱们是拿不到其余页面getInitialProps()方法初始话的数据的,若是对getInitialProps()不了解,请翻阅很简单的next.js数据获取规范或者官方文档 这里能够给你们看一个例子

这里在 getInitialProps()中定义的数据并无显示出来

class MyApp extends App {
    static getInitialProps = async ({Component}) => {
        let pageProps;
        if(Component.getInitialProps) {
            pageProps = await Component.getInitialProps()
        }
        return {
            pageProps
        }
    }

    render() {
        const { Component, pageProps } = this.props;
        console.log(Component);

        return (
            <Container> <Component {...pageProps} /> </Container> ) } } 复制代码

这里在MyApp中新增了一个getInitialProps方法,注意他是一个静态方法,因为其余页面可能设置了getInitialProps也可能没有设置,因此这里须要判断一下,而且这个方法为异步方法,执行时注意加上await并在外层方法添加async。这样就能够将其余页面中getInitialProps设置的属性引入过来,而且传递给Component就能够显示了,来看看效果吧

这里就能够正常打印了

管理全局数据举例

state = {
    counter: 20
}
复制代码

例如在MyApp中定义counter,就能够传递给全部组件 布局示例 在components目录下建立Layout.jsx

import Link from 'next/link';
import { Button } from 'antd'

export default ({ children }) => {
    return (
        <> <div className="header"> <Link href="/a?id=1"><Button>跳转A</Button></Link> <Link href="/test/b"><Button>跳转B</Button></Link> </div> <div className="body"> {children} </div> </> ) } 复制代码

而后在_app.js中引用

return (
    <Container> <Layout> <Component {...pageProps} /> </Layout> </Container> ) 复制代码

这样每一个页面都会显示Layout了

自定义Document

只有在服务器端渲染的时候才会被调用,主要用来修改服务端渲染的文档内容,一般实现服务端渲染会使用一些css-in-js库(styled-jsx是 Next.js自带默认使用的css-in-js库) 它在_document.js中定义

import Document, {Html, Head, Main, NextScript} from 'next/document'

class MyDocument extends Document {
    render() {
        return (
            <Html> <Head> </Head> <body> <Main /> <NextScript /> </body> </Html>
        )
    }
}
export default MyDocument
复制代码

next/document中提供的并不只是Document组件,还有一些跟HTML标签对应的组件,在重写的时候要记得都要写上。

在Head中试着添加一些内容

<Head>
    <title>My Next.js</title>
    <style>{`* { color: red}`}</style>
</Head>
复制代码

设置getInitialProps

再说明一下,document只有在服务端渲染时候才会执行。

在重写Docuemnt的时候,咱们也能够重写getInitialProps方法,这个getInitialProps来自于Document组件。

static getInitialProps = async (ctx) => {
    const props = await Document.getInitialProps(ctx)

    return {
        ...props
    }
}
复制代码

这里的getInitialProps也是个静态方法,而且也要加async,由于里面使用了await,而且注意有个参数ctx,咱们能够不重写它,可是若是咱们要重写就要按照这个格式来重写,而后在里面再添加本身想要的东西。

结束

本文内容是比较简单的,可是很重要,在使用next.js开发项目中是要常用的,因此仍是掌握好它吧。在后面集成css in js样式文章中可能还会再比较详细地描述在_docuemnt.js中咱们能够干点什么,但愿对入门级小伙伴有所帮助。

相关文章
相关标签/搜索