Install required
Run the following command to write TypeScript
1 2 3 4 | # Install required libraries because they are described in typescript # Execute in the Next.js project root npm install --save-dev typescript @types/react @types/react-dom @types/node |
Create screen template
Before creating screens, create a sample file.
In this sample file we will define common for header and footer.
※ This article does not focus on style, so it will use the bulma of CSS framework.
Create layout.tsx file in Components folder.
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | // /src/app/components/layout.tsx import * as React from 'react' import Head from 'next/head' type Props = { title?: string isHeader?: boolean isFooter?: boolean } function getHeader(title: string) { return ( <header> <section className="hero is-dark"> <div className="hero-body"> <div className='container'> <h1 className="title">{title}</h1> </div> </div> </section> </header> ); } function getFooter() { return ( <footer className="footer"> <div className="content has-text-centered"> <p>Next Test Screen</p> </div> </footer> ); } const Layout: React.FunctionComponent<Props> = ({ children, title = 'Next Sample Screen Title', isHeader = true, isFooter = true, }) => ( <div> <Head> <title>{title}</title> <meta charSet="utf-8" /> <meta name="viewport" content="initial-scale=1.0, width=device-width" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"></link> <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script> <link rel="icon" type="image/x-icon" href="/static/favicon.ico" /> </Head> {isHeader && (getHeader(title))} <section className="section"> <div className="container"> {children} </div> </section> {isFooter && (getFooter())} </div> ) export default Layout |
Through the function getHeader () and getFooter () function to describe the individual processing by variables.
Create original scrolling screen
Create a screen like the login screen to make the original screen move.
Create the login.tsx file in the Pages folder.
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | // /src/app/pages/login.tsx import * as React from 'react' import Router from 'next/router' import Layout from '../components/layout' interface LoginProps {} interface LoginState { credentials: { email: string password: string } isLoading: boolean } class Login extends React.Component<LoginProps, LoginState> { constructor(props: LoginProps) { super(props) this.state = { credentials: { email: null, password: null, }, isLoading: false } } handleCredentialsChange = (e: React.ChangeEvent<HTMLInputElement>) => { let { credentials } = this.state credentials[e.target.name] = e.target.value this.setState({ credentials }) } handleLoginSubmit = (e: React.MouseEvent<HTMLElement>) => { e.preventDefault() this.setState({ isLoading: true }) setTimeout(() => { this.setState({ isLoading: false }) // Screen transition to / user when button is pressed Router.push('/user') // Router.replace('/user') }, 1000) } public render() { return ( <Layout title="Login" isHeader={false} isFooter={false}> <form action=""> <div className="login-area"> <div> <h1 className=""><img src="/static/Nexttch_black.png" alt="my image" /></h1> </div> <article className="box is-rounded"> <div className="field"> <label className="label">Email</label> <p className="control has-icons-left"> <input className="input" type="email" placeholder="Email" /> <span className="icon is-small is-left"> <i className="fas fa-envelope"></i> </span> </p> </div> <div className="field"> <label className="label">Password</label> <p className="control has-icons-left"> <input className="input" type="password" placeholder="Password" /> <span className="icon is-small is-left"> <i className="fa fa-lock"></i> </span> </p> </div> <div className="field"> <p className=""> <button className="button is-medium is-info is-fullwidth" onClick={this.handleLoginSubmit}>ãƒã‚°ã‚¤ãƒ³</button> </p> </div> </article> </div> </form> <style jsx> {` .login-area { margin: 0 auto; min-width: 375px; max-width: 400px } .box { padding-top: 3rem; } h1 { padding: 3rem 6rem; text-align: center; } .field { padding-bottom: 1.5rem; } `} </style> </Layout> ); } } export default Login; |
Create a moving target screen
Create screens like the My Page screen to make the target screen move.
Install library needed to call API.
1 2 3 | # Install isomorphic-unfetch npm install --save isomorphic-unfetch |
** Create a user.tsx file in the Pages folder
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | // /src/app/pages/user.tsx import * as React from 'react' import Layout from '../components/layout' import fetch from "isomorphic-unfetch"; interface UserProps { data: { name: string enname: string birthday: string constellation: string } } class User extends React.Component<UserProps> { constructor(props: UserProps) { super(props) } static async getInitialProps(ctx: any) { try { let response; response = await fetch("http://localhost/api/user"); const json = await response.json(); return { data: json.data }; } catch (e) { console.error(e); return { data: [] }; } } public render() { return ( <Layout title="Next Sample Test Screen"> <div className="message is-info user-area"> <h1 className="message-header">Introduction</h1> <div className="description"> <figure className="image is-128x128"> <img className="is-rounded" src="/static/Nextgisawa.jpg" /> </figure> </div> <p className="description name">{this.props.data.name}</p> <p className="description en-name">{this.props.data.enname}</p> <p className="description birthday">{this.props.data.birthday}</p> <p className="description constellation">{this.props.data.constellation}</p> </div> <style jsx> {` .user-area { margin: 0 auto; min-width: 375px; max-width: 600px; padding-bottom: 3rem; margin-bottom: 3rem; } .description { margin-top: .2rem; text-align: center; } .description figure { margin-top: 2rem; margin-bottom: 2rem; top: 0; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); } .name { margin-top: 1rem; font-size: 1.4rem; font-weight: bold; line-height: 1.6rem; } .en-name { letter-spacing: -.05rem; } .birthday { font-size: .9rem; margin-top: .75rem; } .constellation { font-size: .9rem; margin-top: -.2rem; } `} </style> </Layout> ); } } export default User |
When displayed, the screen will run the getInitialProps () function and call API http: // localhost / api / user
Handling external API calls
Create call handling with the file created above.
Depending on the location described on the component and the page, it can be run by either the server or the client. In the case of an SSR structure, it is not possible to call an external API on the client side.
Here’s how to make the API callable through the Next.js server.
Create API called on Next.js side
1 2 3 4 5 6 7 8 | // /src/app/pages/api/user.ts export default async(req, res) => { // Call external API const response = await fetch("http://study-next_web_1:8081/user.php"); const data = await response.json(); res.status(200).json(data); } |
Note: The study-next_web_1 section is the name of the container, so change it to match the container name used.
Create external API handler
Create user.php in the web directory, create php to use with json.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php // /src/web/user.php $array = [ 'result' => 'OK', 'data' => [ 'name' => 'NEXT SAMPLE', 'enname' => 'NEXT SAMPLE', 'birthday' => '1999.09.09', 'constellation' => 'Virgo' ] ]; header('Access-Control-Allow-Origin: *'); header('Content-Type: application/json'); echo json_encode($array); |
Last words
Above is a simple description of how to create a screen in the template, move the screen and get data from the external server.