Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

orquidz's avatar

Inertia.js and Vue.js: Reactivity Issue with Nested Component Rendering in Laravel SPA

I'm building a Laravel and Vue.js SPA using Inertia.js. When I initially rendered the todos directly in the Home page, data updates on newly created todos. However, after introducing a TodoList component to handle the rendering, the data doesn't update as expected after adding a new todo (unless with a manual page reload). The TodoList component receives the todos prop but doesn't reactively update when new data is available.

Here are code the code snippets:

web.php:

Route::get('/', [TodoController::class, 'index'])->name('index');
Route::apiResource('todos', TodoController::class);

todoController.php:

class TodoController extends Controller
{
    //
    public function index()
    {
        return Inertia::render('Home', [
            'todos' => Todo::latest()->get()->toArray(),
        ]);
    }

    public function store(Request $request)
    {
        Todo::create([
            'task' => $request->input('task'),
        ]);

        return redirect()->to('/');


    }

}

Home.vue:

<template>
    <TodoList :todos="todos" />
</template>

<script setup>
import TodoList from "./TodoList.vue";

defineProps(["todos"]);
</script>

TodoList.vue:

<template>
    <div class="w-2/3 flex flex-col justify-center">
        <Todo v-for="todo in todos" :key="todo.id" :todo="todo" />
    </div>
</template>

<script setup>
import Todo from "./Todo.vue";

defineProps(["todos"]);
</script>

Todo.vue:

    <template>
        <form @submit.prevent="addTodo" class="relative">
            <input
                class="p-3 pr-12 w-full rounded-md"
                type="text"
                name="todo"
                id="todo"
                placeholder="Create a new todo..."
                v-model="todoForm.task"
            />
            <button
                class="absolute text-white flex justify-center items-center top-1 right-1"
            >
                <span
                    class="text-white bg-indigo-600 rounded-full text-5xl h-10 w-10 leading-[30px]"
                    >+</span
                >
            </button>
        </form>
    </template>

    <script setup>
    import { useForm } from "@inertiajs/vue3";
    const todoForm = useForm({
        task: "",
    });

    const addTodo = () => {
        todoForm.post("/todos", {
            onSuccess: () => {
                todoForm.reset("task");
            },
        });
    };
    </script>


I tried wrapping the todos being passed as props with "ref" reactivity api, no results.

0 likes
1 reply
orquidz's avatar

Found the problem, silly me, I forgot to add the "key" for each todo in my code, but included it in the question, It works fine, Tehee

Please or to participate in this conversation.