How to change the original value passed as props in vue3?

Viewed 1721

Assume you have a todo-list component that will render the passed todos for you. where the todos is an Ref object.

<todo-list :todos="todos"/>

And the todo-list component also allow user to delete any of the passed todos.

But vue3 won't let us to mutate the props.todos object.

So the only way to do this is make a clone of props.todos, then if user click on the delete button, remove the item from that cloned one to update the view. But this approach won't make change to the original passed todos Ref object.

Another way to workaround this is emit an itemDeleted event from the todo-list, listen it from it's parent component, then remove the deleted item from the original passed todos Ref object in the listener.

But I want to keep all the logic inside of the todo-list itself, so I want to know if there is any way to change the original todos Ref object inside the todo-list component.

I know a better solution could be using v-model:todo-list, and emit a update:todo-list event to update the original todo-list Ref object. But I'm wondering if I can do this without the v-model directive.

2 Answers

Put the todos in separate file called useTodo.js which defines a composable function that could be reusable across multiple components without using any inner property or passing props :

import {ref} from 'vue'
const todos=ref([])

const useTodo= () => {

 setTodos(_todos){
       todos.value=_todos;
  }

return {todos, setTodos}
}

export default useTodo

then import it in both parent todolist components

parent component :

<todo-list />
...
import useTodo from './useTodo'
...

setup(){
    const {todos, setTodos}=useTodo();
    //use todos instead of your todos with ref

}

in todolist component :

...
import useTodo from './useTodo'
...

setup(){
    const {todos, setTodos}=useTodo();
     //use todos instead of props.todos

}

Another way to workaround this is emit an itemDeleted event from the todo-list, listen it from it's parent component, then remove the deleted item from the original passed todos Ref object in the listener.

This is the ideal way of solving this type of problem.

The Vue philosophy is props down, events up. See: https://medium.com/quick-code/vue-communication-patterns-an-intro-to-props-down-and-events-up-pattern-d53340d2c94

As components grow progressively more complex keeping the logic that actually edits the data in the same top level component that stores the data is preferable.

Related