点数
80点
感想
前編で作成したAPIを使用するためのページをNext.jsで作成していく、という内容だった。
特に複雑な処理もなく、問題なく最後まで読み終えることができた。
ユーザー関連ページ
ユーザー登録ページの作成
- mkdir pages/user/
- touch pages/user/register.js
- Reactではform送信はonSubmitで処理するので、action, methodはformタグに書かない。
- フォームはJSON.stringify()でJSONにして送信する。
- fetch(), json()はPromiseを返却するのでawaitを付ける
import { useState } from 'react'
const Register = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:3000/api/user/register', {
method: 'POST',
headers: {
'Accrpt': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: name,
email: email,
password: password,
})
});
const json = await response.json();
alert(json.msg);
} catch (err) {
alert('登録失敗');
}
};
return (
<>
<h1>ユーザー登録</h1>
<form onSubmit={handleSubmit}>
<p>name: <input type="text" name="name" value={name} onChange={e=>setName(e.target.value)} required /></p>
<p>email: <input type="text" name="email" value={email} onChange={e=>setEmail(e.target.value)} required/></p>
<p>password: <input type="text" name="password" value={password} onChange={e=>setPassword(e.target.value)} required/></p>
<p><button type="submit">登録</button></p>
</form>
</>
)
};
export default Register;
ログインページの作成
- touch pages/user/login.js
import { useState } from 'react'
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:3000/api/user/login', {
method: 'POST',
headers: {
'Accrpt': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
})
});
const json = await response.json();
localStorage.setItem('token', json.token); // 成功時のみ保存する場合は if (response.ok) {}で囲む必要あり
alert(json.msg);
} catch (err) {
alert('ログイン失敗');
}
};
return (
<>
<h1>ログイン</h1>
<form onSubmit={handleSubmit}>
<p>email: <input type="text" name="email" value={email} onChange={e=>setEmail(e.target.value)} required/></p>
<p>password: <input type="text" name="password" value={password} onChange={e=>setPassword(e.target.value)} required/></p>
<p><button type="submit">ログイン</button></p>
</form>
</>
)
};
export default Login;
アイテムページ
全アイテム表示ページの作成
- mkdir pages/item/
- touch pages/item/index.js
import Link from "next/link";
const Index = (props) => {
return (
<>
{ props.allItems.map(item=> {
return <p key={item._id}><Link href={`item/${item._id}`}>{item.title}</Link>: {item.description}: {item.price}: {item.email}</p>
})}
</>
)
};
export default Index;
export const getServerSideProps = async () => {
const response = await fetch('http://localhost:3000/api/item/readall');
const allItems = await response.json();
return {
props: allItems
}
};
詳細ページの作成
- touch pages/item/[id].js
- ルートパラメータはcontext.queryから取得可能
import Link from "next/link";
const SingleItem = (props) => {
return (
<>
<h1>{props.item.title}</h1>
<h2>{props.item.description}</h2>
<h3>{props.item.price}</h3>
<h3>{props.item.email}</h3>
<Link href={`/item/update/${props.item._id}`} style={{marginRight: '10px'}}>編集</Link>
<Link href={`/item/delete/${props.item._id}`} style={{marginRight: '10px'}}>削除</Link>
<Link href="/item">一覧へ戻る</Link>
</>
)
};
export default SingleItem;
export const getServerSideProps = async (context) => {
const response = await fetch(`http://localhost:3000/api/item/${context.query.id}`);
const item = await response.json();
return {
props: item
}
};
作成ページの作成
- touch pages/item/create.js
- 前編にてutils/auth.jsでconst token = req.headers.authorization.split(' ')[1];としているので、HTTPヘッダにAuthorizationを付与する
- JWTではトークンを「Bearer xxxxxxxxxx」とするのが慣習である
import { useState } from 'react'
const CreateItem = () => {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [price, setPrice] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:3000/api/item/create', {
method: 'POST',
headers: {
'Accrpt': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
body: JSON.stringify({
title: title,
description: description,
price: price,
})
});
const json = await response.json();
alert(json.msg);
} catch (err) {
alert('登録失敗');
}
};
return (
<form onSubmit={handleSubmit}>
<h1>アイテム作成</h1>
<p>title: <input type="text" name="title" value={title} onChange={e=>setTitle(e.target.value)} required/></p>
<p>description: <input type="text" name="description" value={description} onChange={e=>setDescription(e.target.value)}/></p>
<p>price: <input type="text" name="price" value={price} onChange={e=>setPrice(e.target.value)}/></p>
<p><button type="submit">投稿</button></p>
</form>
)
};
export default CreateItem;
コメント