mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
[with-typescript] Improved intial props examples, added example detail (#6165)
I've just thought of a way to improve the initial props page by adding an example for a list/detail page structure. To do that, I've created a separate `/detail` page, and a mock API which calls data from the array we made on the previous PR. A ListDetail component is created as an example for displaying detail. Page structure is also cleaned up. Should I go ahead and add an example on how to style with styled-jsx + its TS declarations? I might decide to do it within this week anyway.
This commit is contained in:
parent
968475fb95
commit
8fdb133903
|
@ -16,8 +16,8 @@ const Layout: React.FunctionComponent<Props> = ({ children, title = 'This is the
|
|||
<header>
|
||||
<nav>
|
||||
<Link href='/'><a>Home</a></Link> | {' '}
|
||||
<Link href='/list-fc'><a>List as Functional Component</a></Link> | {' '}
|
||||
<Link href='/list-class'><a>List As Class</a></Link> | {' '}
|
||||
<Link href='/list-class'><a>List Example</a></Link> | {' '}
|
||||
<Link href='/list-fc'><a>List Example (as Functional Component)</a></Link> | {' '}
|
||||
<Link href='/about'><a>About</a></Link> | {' '}
|
||||
</nav>
|
||||
</header>
|
||||
|
|
16
examples/with-typescript/components/ListDetail.tsx
Normal file
16
examples/with-typescript/components/ListDetail.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import IDataObject from '../interfaces';
|
||||
|
||||
type ListDetailProps = {
|
||||
item: IDataObject;
|
||||
}
|
||||
|
||||
const ListDetail: React.FC<ListDetailProps> = ({ item: user }) => (
|
||||
<div>
|
||||
<h1>Detail for {user.name}</h1>
|
||||
<p>ID: {user.id}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default ListDetail;
|
|
@ -1,4 +1,6 @@
|
|||
import * as React from 'react'
|
||||
import Link from 'next/link';
|
||||
|
||||
import IDataObject from '../interfaces'
|
||||
|
||||
type Props = {
|
||||
|
@ -6,7 +8,9 @@ type Props = {
|
|||
}
|
||||
|
||||
const ListItem: React.FunctionComponent<Props> = ({ data }) => (
|
||||
<React.Fragment>{data.id}:{data.name}</React.Fragment>
|
||||
<Link href={`/detail?id=${data.id}`} passHref>
|
||||
<a>{data.id}: {data.name}</a>
|
||||
</Link>
|
||||
);
|
||||
|
||||
export default ListItem
|
||||
|
|
|
@ -4,6 +4,7 @@ import Layout from '../components/Layout'
|
|||
|
||||
const AboutPage: React.FunctionComponent = () => (
|
||||
<Layout title="About | Next.js + TypeScript Example">
|
||||
<h1>About</h1>
|
||||
<p>This is the about page</p>
|
||||
<p><Link href='/'><a>Go home</a></Link></p>
|
||||
</Layout>
|
||||
|
|
46
examples/with-typescript/pages/detail.tsx
Normal file
46
examples/with-typescript/pages/detail.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import * as React from 'react'
|
||||
import { NextContext } from 'next'
|
||||
import Layout from '../components/Layout'
|
||||
import IDataObject from '../interfaces'
|
||||
import { findData } from '../utils/sample-api'
|
||||
import ListDetail from '../components/ListDetail';
|
||||
|
||||
type RequestQuery = {
|
||||
id: number,
|
||||
}
|
||||
|
||||
type Props = {
|
||||
item?: IDataObject,
|
||||
errors?: string,
|
||||
}
|
||||
|
||||
class ListDetailPage extends React.Component<Props> {
|
||||
static getInitialProps = async ({ query }: NextContext<RequestQuery>) => {
|
||||
try {
|
||||
const item = await findData(query.id);
|
||||
return { item }
|
||||
} catch (err) {
|
||||
return { errors: err.message }
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item, errors } = this.props;
|
||||
|
||||
if (errors) {
|
||||
return (
|
||||
<Layout title={`Error | Next.js + TypeScript Example`}>
|
||||
<p><span style={{ color: 'red' }}>Error:</span> {errors}</p>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout title={`${item ? item.name : 'Detail'} | Next.js + TypeScript Example`}>
|
||||
{item && <ListDetail item={item} />}
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ListDetailPage
|
|
@ -1,12 +1,15 @@
|
|||
import React from 'react'
|
||||
import * as React from 'react'
|
||||
import { NextContext } from 'next'
|
||||
import Link from 'next/link';
|
||||
|
||||
import Layout from '../components/Layout'
|
||||
import List from '../components/List'
|
||||
import IDataObject from '../interfaces'
|
||||
import { findAll } from '../utils/sample-api';
|
||||
|
||||
type Props = {
|
||||
items: IDataObject[],
|
||||
pathname: string,
|
||||
}
|
||||
|
||||
class ListClass extends React.Component<Props> {
|
||||
|
@ -14,20 +17,19 @@ class ListClass extends React.Component<Props> {
|
|||
// Example for including initial props in a Next.js page.
|
||||
// Don't forget to include the respective types for any
|
||||
// props passed into the component
|
||||
const dataArray: IDataObject[] = [
|
||||
{ id: 101, name: 'larry' },
|
||||
{ id: 102, name: 'sam' },
|
||||
{ id: 103, name: 'jill' },
|
||||
{ id: 104, name: pathname },
|
||||
]
|
||||
const items: IDataObject[] = await findAll()
|
||||
|
||||
return { items: dataArray }
|
||||
return { items, pathname }
|
||||
}
|
||||
|
||||
render() {
|
||||
const { items, pathname } = this.props
|
||||
return (
|
||||
<Layout title="List Example | Next.js + TypeScript Example">
|
||||
<List items={this.props.items} />
|
||||
<h1>List Example</h1>
|
||||
<p>You are currently on: {pathname}</p>
|
||||
<List items={items} />
|
||||
<p><Link href='/'><a>Go home</a></Link></p>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import { NextFunctionComponent, NextContext } from 'next'
|
||||
import Link from 'next/link';
|
||||
|
||||
import Layout from '../components/Layout'
|
||||
import List from '../components/List'
|
||||
import IDataObject from '../interfaces'
|
||||
import { findAll } from '../utils/sample-api';
|
||||
|
||||
type Props = {
|
||||
items: IDataObject[],
|
||||
pathname: string,
|
||||
}
|
||||
|
||||
const ListFunction: NextFunctionComponent<Props> = ({ items }) => (
|
||||
<Layout title="List Example (with Function Components) | Next.js + TypeScript Example">
|
||||
const ListFunction: NextFunctionComponent<Props> = ({ items, pathname }) => (
|
||||
<Layout title="List Example (as Functional Component) | Next.js + TypeScript Example">
|
||||
<h1>List Example (as Function Component)</h1>
|
||||
<p>You are currently on: {pathname}</p>
|
||||
<List items={items} />
|
||||
<p><Link href='/'><a>Go home</a></Link></p>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
|
@ -17,14 +24,9 @@ ListFunction.getInitialProps = async ({ pathname }: NextContext) => {
|
|||
// Example for including initial props in a Next.js function compnent page.
|
||||
// Don't forget to include the respective types for any props passed into
|
||||
// the component.
|
||||
const dataArray: IDataObject[] = [
|
||||
{ id: 101, name: 'larry' },
|
||||
{ id: 102, name: 'sam' },
|
||||
{ id: 103, name: 'jill' },
|
||||
{ id: 104, name: pathname },
|
||||
]
|
||||
const items: IDataObject[] = await findAll()
|
||||
|
||||
return { items: dataArray }
|
||||
return { items, pathname }
|
||||
}
|
||||
|
||||
export default ListFunction
|
||||
|
|
34
examples/with-typescript/utils/sample-api.ts
Normal file
34
examples/with-typescript/utils/sample-api.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import IDataObject from "../interfaces";
|
||||
|
||||
/** Dummy user data. */
|
||||
export const dataArray: IDataObject[] = [
|
||||
{ id: 101, name: 'Alice' },
|
||||
{ id: 102, name: 'Bob' },
|
||||
{ id: 103, name: 'Caroline' },
|
||||
{ id: 104, name: 'Dave' },
|
||||
];
|
||||
|
||||
/**
|
||||
* Calls a mock API which finds a user by ID from the list above.
|
||||
*
|
||||
* Throws an error if not found.
|
||||
*/
|
||||
export async function findData(id: number | string) {
|
||||
const selected = dataArray.find((data) => data.id === Number(id))
|
||||
|
||||
if (!selected) {
|
||||
throw new Error('Cannot find user')
|
||||
}
|
||||
|
||||
return selected
|
||||
}
|
||||
|
||||
/** Calls a mock API which returns the above array to simulate "get all". */
|
||||
export async function findAll() {
|
||||
// Throw an error, just for example.
|
||||
if (!Array.isArray(dataArray)) {
|
||||
throw new Error('Cannot find users')
|
||||
}
|
||||
|
||||
return dataArray
|
||||
}
|
Loading…
Reference in a new issue