Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Commit

Permalink
feat(_document.js): refactored globalhead to now exist in _document.js
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Danikowski authored and Kevin Danikowski committed Nov 27, 2019
1 parent c429b0d commit 6d013e3
Show file tree
Hide file tree
Showing 16 changed files with 132 additions and 89 deletions.
47 changes: 24 additions & 23 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
{
"env": {
"browser": true,
"es6": true,
"jest": true
"env": {
"browser": true,
"es6": true,
"jest": true
},
"extends": ["airbnb", "prettier"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"extends": ["airbnb", "prettier"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/prop-types": ["error"]
}
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": ["react"],
"rules": {
"react/prop-types": ["error"],
"react/jsx-props-no-spreading": ["warn"],
"react/forbid-prop-types": ["warn"],
"no-unused-vars": ["warn"]
}
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
],
"coveragePathIgnorePatterns": [
"<rootDir>/build/",
"<rootDir>/default/src/pages/_document.jsx",
"<rootDir>/out/",
"<rootDir>/.next/",
"<rootDir>/node_modules/",
Expand Down
1 change: 1 addition & 0 deletions templates/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"collectCoverageFrom": ["**/*.{js,jsx,ts,tsx}"],
"coveragePathIgnorePatterns": [
"<rootDir>/build/",
"<rootDir>/src/pages/_document.jsx",
"<rootDir>/out/",
"<rootDir>/.next/",
"<rootDir>/node_modules/",
Expand Down
9 changes: 8 additions & 1 deletion templates/default/babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
{
"presets": ["@babel/preset-env","next/babel"]
"presets": [
[
"next/babel",
{
"preset-env": { "targets": { "node": "current" } }
}
]
]
}
5 changes: 4 additions & 1 deletion templates/default/eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
},
"plugins": ["react"],
"rules": {
"react/prop-types": ["error"]
"react/prop-types": ["error"],
"react/jsx-props-no-spreading": ["warn"],
"react/forbid-prop-types": ["warn"],
"no-unused-vars": ["warn"]
}
}

This file was deleted.

This file was deleted.

This file was deleted.

17 changes: 17 additions & 0 deletions templates/default/src/components/organisms/PageTitle/PageTitle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'
import PropTypes from 'prop-types'
import Head from 'next/head'

const PageTitle = ({ title }) => {
return (
<Head>
<title key="title">{title}</title>
</Head>
)
}

PageTitle.propTypes = {
title: PropTypes.string.isRequired
}

export default PageTitle
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
import React from 'react'
import ShallowRenderer from 'react-test-renderer/shallow'
import GlobalHead from '.'
import PageTitle from '.'

describe('GlobalHead', () => {
describe('PageTitle', () => {
// Test uses ShallowRenderer.render() instead of TestRenderer.create()
// because <GlobalHead> encapsulates NextJS <Head> which in turn uses
// because <PageTitle> encapsulates NextJS <Head> which in turn uses
// React <Helmet> and Helmet doesn't show up in a normal component render.
it('creates a <head> element suitable for global usage across all pages', () => {
const renderer = new ShallowRenderer();
renderer.render(
<GlobalHead title="mock title for test" />
)
const renderer = new ShallowRenderer()
renderer.render(<PageTitle title="mock title for test" />)
const result = renderer.getRenderOutput()
expect(result).toMatchSnapshot()
})
it('populates the specified page title', () => {
const title = "mockTitle"
const renderer = new ShallowRenderer();
renderer.render(
<GlobalHead title={title} />
)
const title = 'mockTitle'
const renderer = new ShallowRenderer()
renderer.render(<PageTitle title={title} />)
const result = renderer.getRenderOutput()
// Expect a React module with a populated <title>
expect(result.props.children).toEqual(
expect.arrayContaining([
expect.objectContaining({
type: 'title',
props: {
children: title
}
})
])
expect.objectContaining({
type: 'title',
props: {
children: title
}
})
)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PageTitle creates a <head> element suitable for global usage across all pages 1`] = `
<Head>
<title>
mock title for test
</title>
</Head>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './PageTitle'
37 changes: 37 additions & 0 deletions templates/default/src/pages/_document.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* _document is only rendered on the server side and not on the client side
* Event handlers like onClick can't be added to this file
*/
import React from 'react'
import Document, { Html, Head, Main, NextScript } from 'next/document'
import Flavicon from '../components/molecules/Favicon'
import Manifest from '../components/molecules/Manifest'

class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}

render() {
return (
<Html lang="en">
<Head>
{/* HEADER ELEMENTS THAT GO HERE:
* meta tags, global scripts, global stylesheets, rel links, etc.
* Tracking scripts like Google Analytics (try https://github.com/react-ga/react-ga)
*/}
<Flavicon />
<Manifest />
</Head>
<body>
{/* NOSCRIPT: place them inside a new <noscript> tag here */}
<Main />
<NextScript />
{/* FOOTER: If your footer will not change based on api calls, place here, otherwise place in _app.js */}
</body>
</Html>
)
}
}

export default MyDocument
9 changes: 3 additions & 6 deletions templates/default/src/pages/example/second-page/index.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import React from 'react'
import Link from 'next/link'
import GlobalHead from '../../../components/organisms/GlobalHead'
import PageTitle from '../../../components/organisms/PageTitle'

const SecondPage = () => {
return (
<>
<GlobalHead title="Second Page - %%APPNAME%%" />
<PageTitle title="Second Page - %%APPNAME%%" />
<main>
<p>
This is another page at a different URL.
</p>
<p>This is another page at a different URL.</p>
<p>
Return to the

<Link href="/">homepage</Link>
</p>
</main>
Expand Down
16 changes: 12 additions & 4 deletions templates/default/src/pages/index/index.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import React from 'react'
import Link from 'next/link'
import GlobalHead from '../../components/organisms/GlobalHead'
import PageTitle from '../../components/organisms/PageTitle'

const Home = () => {
return (
<>
<GlobalHead title="%%APPNAME%%" />
<PageTitle title="%%APPNAME%%" />
<p>Welcome to the boilerplate React app using NextJS!</p>
<p>
Try navigating to

<Link href="/example/second-page">another page</Link>

and observe the URL changing
</p>
</>
)
}

// estlin-disable-next-line
Home.getInitialProps = async context => {
/* Here you can make your pre-fetch for this page, it's a pre-rendering step
* only available for pages.
* Useful parameters in context object: req, res, query (passed from 4th render argument)
* It expects an object with props to be returned
*/
return {}
}

export default Home

0 comments on commit 6d013e3

Please sign in to comment.