Home > Net >  Prop being passed but not updating the component
Prop being passed but not updating the component

Time:01-16

So I have a function called updateAll(data.items) which should take the array and randomly assign a new name, it appears the data.items is updating when I view in vue dev tools and is being passed to the component but not actually updating the browser

I've also added in my buildData.js this is being used for the same app but in react so was trying to keep it as general as I could

//HomeView.vue

<script setup>
import { reactive, watch } from "vue";
import Hero from '@/components/Hero.vue'
import FunctionButton from '@/components/FunctionButton.vue'
import ItemsContainer from '@/components/ItemContainer.vue';
import * as dataFunc from '@/data/buildData'

const data = reactive({
  items: JSON.parse(localStorage.getItem('items')) || []
})

console.log(data.items)

watch(() => data.items,(newValue) => {
  localStorage.setItem('items', JSON.stringify(newValue))
}, {deep: true});


</script>

<template>
    <div class='w-2/3 mx-auto text-center'>
      <Hero HeroText="The one stop shop to store recipes!" />
      <main>
        <h1 >Recipe Manager</h1>
        <div class='functions gap-4 grid grid-cols-2 md:grid-cols-3 mt-8 mx-auto w-fit'>
          <FunctionButton name="Add new recipe" @click="() => data.items = [...data.items,...dataFunc.buildData(1)]"/>
          <FunctionButton name="Add 100 recipes" @click="() => data.items = [...data.items,...dataFunc.buildData(100)]"/>
          <FunctionButton name="Add 1000 recipes" @click="() => data.items = [...data.items,...dataFunc.buildData(1000)]"/>
          <FunctionButton name="Delete all recipes" @click="() => data.items = dataFunc.deleteAll()"/>
          <FunctionButton name="Edit all recipes" @click="() => data.items = dataFunc.updateAll(data.items)"/>
        </div>
        <ItemsContainer :items="data.items"/>
      </main>
    </div>
</template>

//ItemContainer.vue

<script setup>
import Item from '@/components/Item.vue';

const props = defineProps({
  items: {type: Array, default: () => []},
})
</script>

<template>
    <div
        class='items-container w-full md:w-max bg-gray-800 dark:bg-gray-800 text-white dark:text-black mx-auto mt-12 p-4 space-y-4'>
        <Item
          v-for="item in items"
          v-if="items.length > 0"
          :key="item.id"
          :meal="item"
        /> 
        <p v-else class='text-white'>No items to display</p>
    </div>
</template>

I tried to make this as generic as possible as trying to make a similar app on Vue and React so they could share this

import { v4 as uuidv4 } from 'uuid';

function create(){
    const data = {
        id: uuidv4(), 
        category: category[random(category.length)],
        name: meals[random(meals.length)], 
        prepTime: randomTime(),
        cookTime: randomTime(), 
        isFav: false
    }
    return data
}

function random(max){
    return Math.round(Math.random() * 1000) % max;
}

const meals = [
    "Roast Chicken", "Omelette", "Steak Pie", "Beef Stir Fry", "Fish And Chips", "Tomato And Prawn Risotto", "Pepperoni Pizza", "Cheesy Nachos", "Fajitas", "Baked Potato",
    "Full English Breakfast", "Pancakes", "Chocolate Brownies", "Meatballs With Red Pepper Sauce", "Chicken Cesar Salad", "Beef Burger", "Chips","Macaroni Cheese", "Fillet Steak", "Chicken Wings", 
    "BBQ Ribs", "Tomato Soup", "Prawn Dim Sum", "Pork Gyozas", "Tomato Bruschetta", "Spring Rolls", "Beef Jerky", "Lasagne", "Spagetti Carbonara", "Salmon And Potatoes"
]

const category = [
    "Breakfast", "Lunch", "Dinner"
]

function randomTime(){
    return Math.round(Math.random() * 30)
}

function buildData(count){
    const data = new Array(count);
    for(let i = 0; i<count; i  ){
        data[i] = create();
    }
    return data;
}


function updateAll(currentArray){
    return currentArray.map((item) => {
        return{...item, name: meals[random(meals.length)], }
    })
}

function updateOne(item){
    return{...item, name: meals[random(meals.length)], }
}

function favouriteAll(currentArray = []){
    return currentArray.map((item) => {
        return {...item, isFav: true}
    })
}

function deleteAll(){
    const data = []
    return data;
}

export {buildData, deleteAll, favouriteAll, updateAll, updateOne};

CodePudding user response:

Check the console for errors.

If I take the functionality from HomeView.vue, your ItemContainer.vue and an Item.vue (which you didn't provided), then it works.

Check the working Vue SFC Playground

The code:

App.vue

<script setup>
import { ref, watch, reactive } from 'vue'
import ItemsContainer from './ItemContainer.vue';

const data = reactive({
  items: []
})

console.log(data.items)

watch(() => data.items, (newValue) => {
  alert(JSON.stringify(newValue))
}, {deep: true});
  
const addItem = () => {
    data.items.push({ id: data.items.length, name: 'New Item'})
}  
  
</script>

<template>
    <ItemsContainer :items="data.items"/><br />
  <button type="button" @click="addItem()">Add</button>    
</template>

ItemContainer.vue is the same.

Item.vue

<script setup>
const props = defineProps({
  meal: {
    type: Object, 
    default: {undefined}
  }
})
</script>

<template>
    <div>
         {{JSON.stringify(meal)}}<br />
    </div>
</template>

UPDATE

I've updated the playground with your functions and it still does work well. The problem is somewhere else.

  • Related