In Vue3, I utilize the Provide and Inject feature to handle data changes without triggering a visual update. Instead, I apply a filter() function to remove an item from an

I am currently testing the usage of the provide and inject methods. I have placed the datas and del-function in the parent component to provide, and in the child component, I am dynamically rendering using v-for='data' in datas.

The objective I aim to achieve is: when the "delete button" is pressed, triggering the del-function in the child component should result in an item being deleted from the datas in the parent component, causing the datas provided to update.

Subsequently, the child component receives the updated datas to trigger a visual update, causing a re-render of the v-for. [!!!]

However, upon clicking the "delete button", the datas are updated internally, but visually, no items appear to be deleted.

View rendered cards using v-for

// Parent Vue file
<template>
  <Reslist/>
</template>

<script>

import Reslist from './components/ResList.vue'

export default {
  name: "App",
  components: {
     Reslist
  },
  provide() {
    return {
      datas: this.datas,
      delData: this.delData,
    };
  },
  data() {
    return {
      datas: [
        {
          id: 1,
          name: "wawa",
          age: "18",
        },
        {
          id: 2,
          name: "wmmmfwa",
          age: "1128",
       },
      ],
    };
   },
  methods: {
    delData(id) {
      console.log('delete-id ='+ id);
      const newDatas = this.datas.filter( element => element.id !== id);
      this.datas = newDatas;
      console.log(this.datas);

    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>



// Child Vue file
<template>
   <div v-for='data in datas' :key="data.name">
        <h2>{{data.name}}</h2>
        <p>{{data.age}}</p>
        <button @click='delData(data.id)'>delete</button>
   </div>
</template>
<script>
export default {
    inject:['datas','delData']
}
</script>
<style scoped>
div{
    width: 18.75rem;
    margin: 1.25rem auto;
    border: solid 1px grey;
    padding: 1.25rem;
}
</style>

I understand how to use props to pass data to a child component. My query lies in understanding why [provide and inject] do not function as expected. In the [provide] method, I have already set [datas = this.datas], so I am questioning if my logic contains any errors?

Answer №1

Hey there, buddy!

I managed to find a solution by utilizing computed properties...

I hope you find it useful!

Vue Parent File

<template>
  <Reslist/>
</template>

<script>
import Reslist from './ResList.vue'
import { computed } from '@vue/reactivity'
export default {
  name: "App",
  components: {
     Reslist
  },
  provide() {
    return {
      datas: computed(() => this.datas),
      delData: this.delData,
    };
  },
  data() {
    return {
      datas: [
        {
          id: 1,
          name: "wawa",
          age: "18",
        },
        {
          id: 2,
          name: "wmmmfwa",
          age: "1128",
        },
      ],
    };
  },
  methods: {
    delData(id) {
      console.log('delete-id ='+ id);
      const newDatas = this.datas.filter( element => element.id !== id);
      this.datas = newDatas;
      console.log(this.datas);
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Child Vue File

<template>
   <div v-for='data in datas' :key="data.name">
        <h2>{{data.name}}</h2>
        <p>{{data.age}}</p>
        <button @click='delData(data.id)'>delete</button>
   </div>
</template>
<script>
export default {
  inject:['datas','delData']
}
</script>
<style scoped>
div{
    width: 18.75rem;
    margin: 1.25rem auto;
    border: solid 1px grey;
    padding: 1.25rem;
}
</style>

Setting up Main.js for Computed Properties

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.config.unwrapInjectedRef = true
app.mount('#app')

For more information on this configuration check out: https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity

Answer №2

Your supplied data is not functioning reactively, and according to the Vue.js Documentation, for injected data to behave in a reactive manner, it needs to be provided as a computed property by enclosing it within a computed() function:

This rule states:

Working with Reactivity

To ensure that injections are reactively linked to the provider, a computed property must be provided using the computed() function.

In your scenario, this implementation could resemble the following:

  provide() {
    return {
      datas: computed(() => this.datas),
      delData: this.delData,
    };
  },

With that being said, Vue continually receives updates, improvements, and bug fixes, and in order for complete functionality, it's necessary to incorporate an additional configuration temporarily into your application:

This guideline mentions:

Temporary Config Required

The specified usage involves setting

app.config.unwrapInjectedRef = true
to automatically unwrap computed refs in injected data. This feature will be enabled by default in Vue 3.3, and for now, the config serves as a temporary measure to prevent issues. It will no longer be mandatory post 3.3 release.

Practically, this can be achieved as follows:

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

const app = createApp(App);
app.config.unwrapInjectedRef = true;

app.mount('#app')

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with Counting Digg Button Clicks

I can't figure out why the digg button counter isn't working. I followed the instructions but... The website in question is: . I implemented the code exactly as explained here: But the counter remains at 0. Has anyone encountered a similar iss ...

How can we utilize a loop to continuously sum up numbers until we reach a multiple of another number, let's say when the total is divisible by 4?

I am trying to create a function in JavaScript that will detect when a given number is not a multiple of 4. If the number is not a multiple of 4, I want to add numbers incrementally until it reaches the closest multiple of 4. Here’s what I have so far: ...

The attribute 'split' is not found on the never data type

I have a function that can update a variable called `result`. If `result` is not a string, the function will stop. However, if it is a string, I then apply the `split()` method to the `result` string. This function always runs successfully without crashin ...

Tips for retrieving data from an Excel spreadsheet on an HTML/CSS webpage

I have a single HTML template at this location: . The current page is tailored for the state of Arkansas in the US, but I now need to replicate the design for all 50 states. Each state page will have the same layout, but different content specific to that ...

Is there a way to determine if a Dojo dialog has been successfully loaded on the page?

I have a function that needs to close a Dojo dialog if it is currently open. How can I determine if a dojo dialog is active? Should I rely on pure JavaScript and check for its existence by ID? if (dijit.byId("blah") !== undefined) { destroyRecursive ...

Can html-webpack-plugin be configured to create <style> elements from CSS files?

I am managing a static site with Vue and Webpack. In my project, I have a file named style.css containing global CSS rules which I import using import './styles.css' in my index.js file. Additionally, I have some .vue files that generate their o ...

When NuxtImg is utilized, the image will rotate 90 degrees with Nuxt3 NuxtImg

Recently, I have encountered an issue when using NuxtImg where my images appear rotated by 90°. This problem specifically arises with vertical mobile images that are read from supabase and displayed. Interestingly, the images look fine before uploading th ...

Tips for concealing the ID value within a URL or parameter

I just started learning Angular JS and I have a question about hiding parameters in the URL when clicking on anchor tags to send data to another controller. I don't want any ID or its value to be visible in the URL. Is it possible to hide parameters i ...

Deciphering the Essence of Promise Sequences

In my NodeJS project, I am utilizing Promises and aiming to gain a better understanding of Promise.chains. Within the project, there is one exposed function: This main library function returns a promise and it is intended for users to call. After calling ...

Tips on preventing the occurrence of double encoding in raw JSON output from a view

I am encountering a JavaScript error while attempting to parse JSON data obtained from my controller: Uncaught SyntaxError: Unexpected token & in JSON at position 1 at JSON.parse () at stores:76 This is the code I use to serialize my list of elem ...

Unable to locate a type definition file for module 'vue-xxx'

I keep encountering an error whenever I attempt to add a 3rd party Vue.js library to my project: Could not find a declaration file for module 'vue-xxx' Libraries like 'vue-treeselect', 'vue-select', and 'vue-multiselect ...

The precision of the stopwatch is questionable

Just starting out with JS and jquery, I quickly put together a stopwatch code in JS that seems to work accurately up to 10 minutes. The issue arises after the 10-minute mark where it starts falling a few seconds behind (I compared it to a digital stopwatc ...

Is it possible to pass a JavaScript array to a local variable by reference?

Within my namespace, I have an array defined in JavaScript like this: app.collection.box = []; Additionally, there is a function within the same namespace structured as follows: app.init = function () { var box = this.collection.box; // ... code ...

Having trouble establishing a web socket connection using JavaScript

I'm experiencing an issue trying to connect my web socket to an Amazon instance using a specific IP address. I've had success connecting the web socket with a different IP and port using the Google Rest Client app, but now when I try to connect w ...

Confirm the presence of Cookie and save the data

I'm a beginner in the world of Javascript and Ajax, attempting to save a user's name using cookies. I have created a form where users can input their first name (identified by id = firstName). My goal is to remember this information so that the n ...

Ways to identify when a user presses the back or forward arrow on a browser using JavaScript or jQuery for a non-single page application (

There are only 2 routes available: / and /about When on the following URLs: localhost:8080 -> it displays the home page localhost:8080/about -> it shows the about page If a user opens the home page, clicks on the about button, and goes to the abou ...

Ways to extract information from a JSON array based on its length and content

Here is an example of some data: { "_id": ObjectId("528ae48e31bac2f78431d0ca"), "altitude": "110", "description": [ { "id": "2", "des": "test" } ], "id": "1", "latitude": "24.9528802429251", ...

Linking to a specific div within a Vue.js component

Currently working on a Vue.js project, I am encountering an issue with linking an anchor to a specific div within a component. The anchor in question is as follows: <a href="#porto" class="porto-button">Porto, Portugal</a> Accompanied by the ...

Exploring the data types of dictionary elements in TypeScript

I have a model structured like this: class Model { from: number; values: { [id: string]: number }; originalValues: { [id: string]: number }; } After that, I initialize an array of models: I am trying to compare the values with the o ...

Choose an element based on its position in the index (multiple elements with the same class)

Can you use Javascript or jQuery to select an element by its index? For example: <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> If I have 4 elements with ...