//tips
//smart contract
リストにないidを検索されたらエラー表示を行う設定などを行う前に[id].jsに対応するedit.jsを作成していく。
Next.js のページコンポーネント (/pages/xxx.js) は、通常の React コンポーネントとは違って、上位のコンポーネントから props 情報を渡すことができないため 、[id].js では、ページコンポーネントの実装ファイル内で getStaticProps という関数を定義することで、ページコンポーネントに渡す props 情報を生成できるようにした。
getStaticProps 内で、 URL パラメータ情報(/books/[id] の id の部分の値)を取り出して、それを元に props 情報を生成。
これをeditの方でも対応させたい。
https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing
[id].js/edit.jsとしたいので、構成的にはid.jsの同じところに[id]フォルダを作成して、
[id].js
[id]
|_edit.js
とする方法を模索する。
フォルダ名に動的ルーティングの要素を入れ込むのは下記のようにできるはず。
pages/blog/[slug].js → /blog/:slug (/blog/hello-world)
pages/[username]/settings.js → /:username/settings (/foo/settings)
pages/post/[...all].js → /post/* (/post/2020/id/title)
下記構成にして、eidt.jsを配置。
ID
|_[id].js
[id]
|_edit.js
下記を無事に反映させることができた。
const edit = () => {
return (
<h1>edit</h1>
);
}
export default edit;
<h1>edit</h1>
さらにこれを元のedit.jsに入れ替え、importのルートを少し調整。
これで無事に以前のedit pageを表示させることができた。ただ、ここでは[id]の情報の引き継ぎは行えていないのでそちらを導入していく。
探っていくとrouter.queryで簡単に取得できるとのこと。
const router = useRouter()
const { id, comment } = router.query
return (
<>
<Header />
<h1>Post: {id}</h1>
早速[id]フォルダ下のeditページに変数を追加し確認。
無事にURLから取得した{id}の内容を表示することができた。
あとはカードやmediumをfetchする際にデータベースでuserのidごとに別のものを表示できるように設計し、fetchするURLは定型部分+{id}などの形で分岐させていく流れが良いか。
また、postされているtweet idはデータベースに追加して、個別ページを表示する際に読み込み表示させる。debankも同じ。
Mediumは内容をカードにして登録しているので問題ないが、容量が大きすぎる場合には別途方法を模索する。
json placeholderの形態を新たなjson serverに入れて加工してみる。
https://jsonplaceholder.typicode.com/users
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
現在のjson serverにあるdb.jsonは下記のような形。
[
{
"title": "Yoshi's birthday bash",
"details": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
"category": "reminders",
"id": 1
},
{
"title": "Complete my ninja training",
json-server --watch data/db2.json --port 8001にて仮のdb2.jsonを読み込ませたがエラー。
Data must be an object. Found object.See https://github.com/typicode/json-server for example.
一つのオブジェクトの中に入れ込む必要があるようなので、
{
"users": [各オブジェクト]
}
という形にした。
無事に8001に複数のuserのオブジェクトを持つjsonを作成することができた。
この考え方をもとに8000に置いているdb.jsonの方も工夫する。
現在は"notes": [しかないが、"notes2”:も増やしそちらへのアクセスを確認する。
editのuseEffectを下記のように調整。
useEffect(() => {
fetch('http://localhost:8000/notes'+id)
.then(res => res.json())
.then(data => setNotes(data))
}, [])
これを実行すると{notes.map(note => (がエラーになるようになった。
Returnの手前の変数部分ではidの中身が渡っていないよう。idも{id}も効果なし。
const url ='http://localhost:8000/notes'+{id}
console.log(url);
useEffect(() => {
fetch('http://localhost:8000/notes'+{id})
.then(res => res.json())
.then(data => setNotes(data))
}, [])
console.log("notes")
console.log({id})
console.log(notes)
getstaticpropsを使用してみる。
ルートとパスのイメージが繋がっておらず、
export async function getStaticPaths() {
return {
paths: [
{ params: 'notes' },
{ params: 'notes2' }
],
fallback: true // false or 'blocking'
};
}
としていたが getStaticPathsでID/[id]/editの[id]部分を網羅して定義できている必要があることがエラーで分かった。
[id]の中身を定義していればいいので、db.jsonの内容に関係なく下記で問題ない。db.jsonの数は把握しておく必要があるので多くなってきたらconst paths = data.map(ninja => {のように一度に生成してしまえば良い。
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: true // false or 'blocking'
};
}
getStaticPathsはurlに入る[id]の中身を事前に列挙しておくことだと分かったので、次はgetStaticPropsからメインのコンポーネントに変数を渡す方法を考える。
下記の形で無事にURLの中身の[id]をパラメータとして渡すことができるようになった。
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: true // false or 'blocking'
};
}
export const getStaticProps = async (context) => {
console.log('context')
console.log(context)
const id = context.params.id;
//const res = await fetch('https://jsonplaceholder.typicode.com/users/' + id);
//const data = await res.json();
return {
props: { id }
}
}
export default function edit({id}) {//{
useEffect(() => {
fetch('http://localhost:8000/notes'+id-1)
.then(res => res.json())
.then(data => setNotes(data))
}, [])
あとはimageの探し先についてエラーが出ているので修正。
src="./image.jpg”がpublicを参照せずに機能していない。ここは各々のidに紐づいたimageを表示させたいのでimageのパスをidごとに設定する。
そうなるとdrawerにimageを設定するのは無理があるのか。サインイン前は一般のimage、サインイン後は自身のimageにするなども考えられるが、どちらにせよ個別ページを開くと2枚のimageが表示されてしまうので表示しない方がスッキリしそう。
代わりにロゴなどを入れておくといいかもしれない。
export default function MyImage(props) {
let fname = './' + props.fname
let size = props.size + "px"
return (
// <img width={size} border="1"
<img width={size} border="0"
src={fname} />
)
}
ユーティリティ関数 url() は、public ディレクトリ以下のファイルを参照するときに、正しい URL に補正してくれるようなのでこちらも試してみる。
https://maku.blog/p/xjjbwes/