前回の記事 で書いたコードを改善していく。
多分初心者向けにかんたんにしようとしてくれていて、フォーム周りをReact系技術なしで書かれていたので、それをReact + TypeScriptぽくしていく。
目次
問題のコード
app/memos/components/MemoForm.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const MemoForm = ({ initialValues, onSubmit }: MemoFormProps) => { return ( <form onSubmit={(event) => { event.preventDefault() onSubmit(event) }} > <input placeholder="タイトル" defaultValue={initialValues.title} /> <textarea placeholder="本文" defaultValue={initialValues.body} /> <button>Submit</button> </form> ) }
|
ここでonSubmitでeventを渡した結果、
app/memos/pages/memos/new.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <MemoForm initialValues={{}} onSubmit={async (event) => { if (currentUser) { try { const memo = await createMemoMutation({ data: { title: event.target[0].value, body: event.target[1].value, user: { connect: { id: currentUser.id } }, }, }) alert("succress") router.push(`/memos/${memo.id}`) } catch (error) { alert("error") console.log(error) } } }} />
|
ここで参照する event.target[0].value
がany型になってしまっている。
これをいい感じに修正したい。
パッと思いつく改善をやってみる
とりあえず自分が持ってる知識だけでぱぱっと解決してみようと思う。
app/memos/components/MemoForm.tsx
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
| import React, { useState } from "react" import {MemoCreateFormInput} from '../pages/memos/new'
type MemoFormProps = { initialValues: any onSubmit: (props: MemoCreateFormInput) => void }
const MemoForm = ({ initialValues, onSubmit }: MemoFormProps) => { const [title, setTitle] = useState('') const [body, setBody] = useState('')
return ( <form onSubmit={(event) => { event.preventDefault() onSubmit({title: title, body: body}) }} > <input placeholder="タイトル" defaultValue={initialValues.title} onChange={(event) => {setTitle(event.target.value)}} /> <textarea placeholder="本文" defaultValue={initialValues.body} onChange={(event) => {setBody(event.target.value)}}/> <button>Submit</button> </form> ) }
export default MemoForm
|
useStateを使って入力値を取得し、それをonSubmit関数に渡す。
app/memos/pages/memos/new.tsx
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
| // 中略
export type MemoCreateFormInput = { title: string, body: string }
const NewMemoPage: BlitzPage = () => { const router = useRouter() const [createMemoMutation] = useMutation(createMemo) const currentUser = useCurrentUser()
return ( <div> <h1>Create New Memo</h1>
<MemoForm initialValues={{}} onSubmit={async (props: MemoCreateFormInput) => { if (currentUser) { try { const memo = await createMemoMutation({ data: { title: props.title, body: props.body, user: { connect: { id: currentUser.id } }, }, }) alert("succress") router.push(`/memos/${memo.id}`) } catch (error) { alert("error") console.log(error) } } }}
//中略
|
onSubmitで要求する引数はこっちでtypeを定義しておき、あとはその引数の中身を使ってcreateMemoMutationする。
これでとりあえずどこにもany型が登場しない形になった。
ところで、この状態でcommitしようとするとterminalに次のエラーが出た。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| app/memos/pages/memos/[memoId]/edit.tsx:29:32 - error TS2339: Property 'target' does not exist on type 'MemoCreateFormInput'.
29 title: event.target[0].value, ~~~~~~
app/memos/pages/memos/[memoId]/edit.tsx:30:31 - error TS2339: Property 'target' does not exist on type 'MemoCreateFormInput'.
30 body: event.target[1].value, ~~~~~~
Found 2 errors.
rhusky > pre-push hook failed (add --no-verify to bypass) error: failed to push some refs to 'git@github.com:sKawashima/blitz-memo.git'
|
edit側のコンポーネントで要求しているパラメータがformのコンポーネントで指定しているpropsにないことによるエラー。
エラーで教えてくれるの嬉しい。
ので、とりあえず直していく。
といっても一瞬だった。
app/memos/pages/memos/[memoId]/edit.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13
| <MemoForm initialValues={memo} onSubmit={async (props) => { if (currentUser) { try { const updated = await updateMemoMutation({ where: { id: memo.id }, data: { title: props.title, body: props.body, user: { connect: { id: currentUser.id } }, }, })
|
よく考えたら app/memos/components/MemoForm.tsx
で MemoCreateFormInput
importしなくても保管効くよなあ…って思った。
VSCodeに感謝。
次回予告:React Final Form を使ってみる
と書いてみたけど、どうなんだろう。
ざっくりドキュメント見てみたけど現状とどれくらい差が出るのかぴんと来ていない。
でもまあ、BlitzのRecommendだったし一応触ってみることにしようかな。
今日はここまで。
余談
参考にしているサイトには続編が来ていることを確認。
タグ「Blitz.js」の記事一覧 - bagelee(ベーグリー)
早く追いつこう。