起きたこと
todoアプリの編集機能を作成中に起きたエラー。
各オブジェクト毎に値を制御できるようにした後、更新ボタンを押すと以下のようなエラーとなった。
TypeError: Cannot read properties of undefined (reading 'name')
「nameが定義されてないよ〜」と怒られている。
関連のある技術
- Vue3
解決したいこと
nameキーにアクセスできるようにして、更新処理をできるようにしたい
考えるべきこと
今回、関係してる部分は以下なので、その辺を中心に調べていく。
- V-modelの参照してる値を調べる
- editModalTargetのキーバリューの値の保持の仕方
- 更新ボタンを押したときに発火している更新処理の関数(handleUpdateTodo)
- 各行毎の処理が問題ないか調べる
まず、nameキーがないと怒られているので、v-modelで参照してる値を確認してみる。
<v-text-field v-model="editModalTarget.todo.name"></v-text-field>
特にアクセスの仕方に問題はなさそう。。。
次に、editModalTargetの宣言部分とキーバリューの値の保持の仕方を見てみる。
<script setup>
...
const editModalTarget = ref({});
...
const handleOpenModal = (index) => {
editModalTarget.value = {
index: index,
todo: Object.assign({}, todoValues.value[index])
};
showDialog.value = true;
}
...
</script>
refで空のオブジェクトの宣言を行い、編集ボタンを押したときにhandleOpenModal関数が発火する処理となっている。引数には、各indexの要素番号を受け取っている。
editModalTargetの中では、キーにindexとtodo(各todoのstoreのデータ)が指定されていている。
Object.assignとすることで、コピー元である空オブジェクトに対して、各要素のtodoの値がコピーされる。
ここでの指定の仕方も、特に問題なさそう。
となると、更新ボタンを押したときに発火している更新処理の関数が怪しそう。
const handleUpdateTodo = () => {
const updatedTodoList = [...todoValues.value];
updatedTodoList.splice(editModalTarget.value.index, 1, editModalTarget.value.todo);
store.dispatch('updateTodoList', updatedTodoList);
editModalTarget.value = {};
showDialog.value = false;
}
updatedTodoListで、元のコピーを作成。
コピーしてきたupdatedTodoListをspliceで、editModalTarget.value.todoへ置換してそれを、store側へ渡す。
※余談だが、ここまでの処理に1行ずつconsole.logを挿入して処理を見ていくとどこで、エラーになるかわかる。
結果、上記部分では、エラーが出ないことがわかった!
ということは、editModalTarget.valueの初期化が原因である可能性があり、それについて考えてみたところ…
どうやら、モーダル内で編集を終えた後に、editModalTarget.valueをリセットすることで、編集されたtodoの情報が消されて、nameプロパティがないよと怒られていた!
ということで、その部分を削除して、再度実行…
const handleUpdateTodo = () => {
const updatedTodoList = [...todoValues.value];
updatedTodoList.splice(editModalTarget.value.index, 1, editModalTarget.value.todo);
store.dispatch('updateTodoList', updatedTodoList);
showDialog.value = false;
}
できました!!!
今回の事象が起きた要因としては以下になります。
- editModalTarget.value の初期化
初期化する際は、みなさん気をつけましょ〜
おまけ
今回は初期化の処理を消すことで、エラーを解消しましたが、そもそも初期化をしないことになるので、それについて問題ないかを調べる必要があります。
const handleUpdateTodo = () => {
const updatedTodoList = [...todoValues.value];
updatedTodoList.splice(editModalTarget.value.index, 1, editModalTarget.value.todo);
store.dispatch('updateTodoList', updatedTodoList);
showDialog.value = false;
}
text-fieldに表示される値は、store側で保持されている値になります。
編集ボタンを押して、更新処理をしてからモーダルが閉じられるので、store側の値は常に新しい値を持っている事になり、古い値が表示されることはなさそう。