//tips
//smart contract
きちんとrouter.reload()でデータベースの再反映も確認できたので、今度はデータベースへコンテンツを追加する仕組みを作っていく。
現在コンテンツ追加ボタンを押すとhttp://localhost:3000/Createに遷移するが、そうした場合に[id]やfirebase、getStaticPaths、getStaticPropsなどの引き継ぎが必要になるので、まずはeditページ内で完結させられないか考える。
ボタンを押すとboolにより変数をtrueにして表示させるなどを行うことになるか。
最初はそのまま表示させる。
Createのものを持ってくることも考えたが、loginなどのformと同じでよさそうなので表示UIはそちらで対応。
Editのstateに新たに下記を追加。useridをninja[0].useridから持ってきている。
const [title,setTitle]=useState('')
const [details,setDetails]=useState('')
const [subcategory,setScategory]=useState('')
async function handleOnAddcontents(e) {
e.preventDefault();
console.log('add contents')
addDoc(colRef,{
title:title,
details:details,
category:subcategory,
userid:ninja[0].userid,
}).then(()=>{
setTitle('')
setDetails('')
setScategory('')
})
}
このイベントに合わせ、フォームも編集。
Add contents
<form noValidate autoComplete="off" onSubmit={handleOnAddcontents}>
Title
<TextField
onChange={(e)=>setTitle(e.target.value)}
variant="outlined"
color="secondary"
fullWidth
required
/>
Details
<TextField
onChange={(e)=>setDetails(e.target.value)}
variant="outlined"
color="secondary"
fullWidth
required
/>
category
<TextField
onChange={(e)=>setScategory(e.target.value)}
variant="outlined"
color="secondary"
fullWidth
required
/>
<Box textAlign="center">
<Button
type="submit"
varient="contained"
onClick={()=>console.log('aa')}
>
submit
</Button>
</Box>
</form>
これで確認。無事に表示カードに加えることができた。
ただ、この際にドキュメントidは自動生成されることになる。userの保持するドキュメントの中から最新で5つなどを取得し表示させる場合には、タイムスタンプが必要か。
addDoc(colRef,{
title:title,
details:details,
category:subcategory,
userid:ninja[0].userid,
username:ninja[0].username,
date:Date.now()
})
と追加。
下記のように降順に設定すれば最新のものから取れていくはず。
date
1648549194269
1648549149197
最終的にはreload機能も加えて下記のようにした。
async function handleOnAddcontents(e) {
e.preventDefault();
console.log('add contents')
addDoc(colRef,{
title:title,
details:details,
category:subcategory,
userid:ninja[0].userid,
username:ninja[0].username,
date:Date.now()
}).then(()=>{
setTitle('')
setDetails('')
setScategory('')
}).then(()=>{router.reload()})
}
その上でdepositeの表示場所を変更。
onClick={()=>{setFlag(!openflag)}}
{openflag && (
<div></div>
などの条件を設定。
これでクリックしたら開閉ができるようにした。
このようにログイン後は自由にデータベースへの投稿及び削除ができるようになった。
一方で、ログインすると自分以外のuseridの登録内容も操作できるようになってしまう。
自分以外のeditページには入れなくさせたい。
Authのmailと各人の登録mailが異なる場合にはeditページに入れなくしたい。
export default function edit({ ninja })にmailも引き継がせる。
生成されたドキュメントには下記の4つが必ず格納されるようにしておく。
userid:ninja[0].userid,
username:ninja[0].username,
date:Date.now(),
mail:ninja[0].mail
その上でauthの認証情報からemail情報を抽出。
console.log('auth.mail')
console.log(auth.currentUser.email)
こちらはエラー。
フロントエンドでauthの認証情報渡しが行われるためかサーバでは console.log(auth.currentUser)までしか行えず、auth.currentUser.emailがnullとなるのは許されないよう。
[id]での遷移タイミングで問うた方が良さそうなので、
const handleClick = (e) => {
e.preventDefault()
router.push('/ID/'+ninja[0].userid+'/edit')
}
に追加していく。
const handleClick = (e) => {
e.preventDefault()
console.log(auth.currentUser.email)
console.log(ninja[0].mail)
if(auth.currentUser.email==ninja[0].mail){
console.log('Success!')
router.push('/ID/'+ninja[0].userid+'/edit')
}
//router.push('/ID/'+ninja[0].userid+'/edit')
}
これで[id]からの自然な遷移には対応できるようになった。
問題はURLに直接打ち込まれる場合への対処となる。情報を探していくと下記を見つけた。
https://zenn.dev/nus3/scraps/d04f5026bab361
ここでuseeffectを使えないか試す。
useEffect(() => {
if(auth.currentUser.email==ninja[0].mail){
console.log('Success!')
}else{
console.log('NONE')
router.push('/ID/'+ninja[0].userid)
}
}, []);
エラー。そりゃそうか。authの読み込みタイミングが遅いことが問題になっているのだから最初に読み込めるはずもなし。
Authの内容をlocal storageに格納する以外に方法はないのか。
https://jasonwatmore.com/post/2021/08/30/next-js-redirect-to-login-page-if-unauthenticated
Next.js Route Guard Componentという仕組みを作れるか。
グローバルステートを使う方法もあるよう。
こちらも拝見する。
https://zenn.dev/catnose99/articles/2169dae14b58b6#%E6%9C%AA%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AA%E3%82%89%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88%E3%81%99%E3%82%8B%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB
https://www.smashingmagazine.com/2021/06/client-side-routing-next-js/