Troubleshooting a reactivity problem with Nuxt 3/Vue 3 when rendering components within a v-for loop

Hello fellow community members :) I seem to be facing an issue related to reactivity and I could use some advice.

Description

I have a component called FileInput.vue. This component allows me to upload files to my project. Whenever a new image is added, a new field gets pushed to the form.allImages reactive array:

@add="addImageField"

The addImageField function looks like this:

const addImageField = (): void => {
  form.allImages.push({ filename: '' });
};

Here is the reactive data structure:

import type { Images } from '@/types/images.d';

interface Work {
  allImages: Images[];
}

const form: Work = reactive({
  allImages: [{ filename: '' }],
});

Problem description

When I add 2 images and then try to delete the first one using the following function:

const deleteImageField = (index: number): void => {
   form.allImages.splice(index, 1);
};

The first block gets removed correctly and the second one takes its place as expected. However, the second image block should now be empty with a clear value to allow for another image to be added. Although the value of the second element in form.allImages is cleared, the component block still displays the image that belonged to the previous first element in the array.

Check out the image here: https://github.com/nuxt/nuxt/assets/73745478/74981582-05ea-4910-9387-7240dc4394c2

Reproduction

You can see the reproduction by visiting this link: https://stackblitz.com/edit/nuxt-starter-qeaeuf?file=app.vue.

How to use the reproduction

Click on the Add Image block, select any image from your PC, and a static favicon.ico file will be displayed as an example. You will also see a Delete button for deleting the image. Above all the blocks, you can track the data using the {{ form.allImages }}.

Expected behavior

After deleting the image block, it should be completely empty (without displaying any image) and ready for the user to upload a new one.

**I appreciate your attention and any help would be greatly appreciated :) If you have suggestions for improving the code, please feel free to share them as well. Thank you.**

Answer №1

To ensure that your key in the v-for is effective, it should be placed on the same element as the v-for. Avoid using the index as the key since it may not provide a unique identifier for each item, especially when elements are being added or removed from an array.

An easy fix is to include a unique id field based on a counter variable that increments every time a new item is added to the array.

interface Images {
  filename: string
  id: number
}

let count = ref(0);
const form: Work = reactive({
  allImages: [{ id: count.value++, filename: '' }],
});

const addImageField = (): void => {
  form.allImages.push({ id: count.value++, filename: '' });
};

Update your v-for loop with:

<div v-for="(image, index) in form.allImages" :key="image.id" 

Check out the updated StackBlitz demo


Other issues addressed:

const { text, required, modelValue } = props;
  1. Avoid destructuring props as it can cause reactivity loss. Access props inside the setup() function using props.propName, outside setup as this.propName, or directly in the template as propName. No need to return props from setup, as they are automatically returned.

  2. Rename your custom Button component to avoid conflicts with the HTML reserved <button> element.

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

Three.js Pin Placement for Clothing

I am in need of assistance! I am currently working on a simulation involving a cloth that is attached to four corners. I am attempting to reposition the pins at coordinates 0, 10, 88, 98 within a 10x10 array. My goal is to place each pin at a different pos ...

When attempting to add a variable using the next() function, I encountered an error with the BehaviorSubject. The error message displayed was "this.count.next is not a function"

In my Angular service, there is a variable called count that I need to monitor for updates. Whenever this count variable is updated, I want to assign its new value to another variable in a separate component. import {BehaviorSubject} from "rxjs/BehaviorSu ...

"Can anyone help me figure out why my 'for' loop is only retrieving the final item in my HTML code

After reading about JavaScript closures inside loops and why only the last item is displayed in a loop, I still can't figure out the issue. So, I decided to seek help by posting my code here. function Produit(nom, prix){ this.nom = nom; this. ...

How to eliminate the yellow box in Three.JS when working with EdgesGeometry, LineSegments, and BoxHelper

Three.js Version: 82 I recently came across an interesting example on the official Three.js website: In this example, I noticed the presence of yellow boxes surrounding the 3D models. Previously, in version 79, I used THREE.EdgesHelper to outline the 3D ...

Is the webdriver.io waituntil method designed to return a boolean value of true or false

I am working on an automation framework using webdriver.io v5. I need to receive a boolean response from the code snippet below: waitAndCheckForContactToBePresent(contactName) { return browser.waitUntil((value) => { return this.chec ...

Assistance needed with implementing jQuery tabs

I'm looking to add a link that takes me directly to content within a non-default tab on another page. Here's the code snippet that explains what I need: My Code: This is from my profile_edit.php page: The javascript: <script src="Javascrip ...

What are the best practices for effectively managing jQuery UI sliders?

I am currently developing a web application that involves updating jQuery UI sliders using JavaScript. While I have managed to resolve most of the issues related to updating the slider after initialization, there is one particular issue that remains unreso ...

When a user inputs in the field, it automatically loses focus

An error is encountered in two scenarios: When the input includes an onChange event handler When the input is located within a component that is called on another page For instance: In Page1.js, we have: return <div> <Page2 /> </div ...

What is the best way to continuously run a series of setInterval() functions in a never-ending

I attempted to create a function that would post measurement A every 5 seconds for 10 times, followed by posting measurement B at random intervals. The goal was to have this function repeat indefinitely in order to simulate a fake agent. My initial code l ...

What is the most efficient way to incorporate MongoDB into your codebase using ES6-style

I have encountered an issue with importing MongoDB using the es6 import-from style. When I try to import using node's require method, everything works fine. let mongo = require('mongodb'); let MongoClient = mongo.MongoClient; However, when ...

Polygon drawing not displaying on openlayers map

My task is to draw a polygon on an OpenLayers map. The code I am using for this purpose is as follows: draw = new Draw({ source: this.vectorSource, type: 'Polygon' }) draw.on('drawend', e => { ...

Managing extensive amounts of data with server-side scripting in a Datatable

I am exploring the use of the datatable plugin to effectively manage a large amount of data. Currently, I am interested in implementing "server side processing in datatables" with the help of server-side scripting. Since I have limited experience with AJA ...

Can anyone provide guidance on showcasing data received from Laravel resource in a Vue Component?

I've been honing my skills in Vue and am grappling with how to manage data passing. Within my Vue component, I have a link that looks like this: <a class="btn btn-success" :href="'/projectpage/' + project.id">Bid</a>, and I found ...

How come React.js is not displaying images from local URLs?

In my React application, there is a form where users can submit an image file. To store the path of the submitted image locally for browser access, I utilized URL.createObjectURL to generate a URL for the file. Here is the code snippet: handleImageChange(e ...

Merging an AppBar and Drawer in Material UI for a seamless user interface design

I am working on integrating an AppBar component with a drawer feature. Here is the code for the AppBar: import React from "react"; import PropTypes from "prop-types"; import { withStyles } from "material-ui/styles"; import AppBar from "material-ui/AppBar" ...

Master the art of MongoDB Aggregate with these simple steps!

Here is a sample data object: [ { "_id": "56bab”, "region": “AS”, “spentOn”: [ “56bf623a0c90b5” ] }, { "_id": "57bab", "region": "EU", "spentOn": [ "b5”, "b6”, "b8”, ] }, ...

The authentication status of req.isAuthenticated for Passport is consistently marked as untrue

I am having issues with my authentication system. Let's start by looking at my node.js file: //Initializing Express Web Server var express = require('express'); var app = express(); var http = require("http").Server(app); var lusca = requi ...

Generate an array using hyperlinks within a list item created by the user

In the process of developing a program, I have included a feature where users can drag and drop .wav files into a playlist-container. These files are then played in the order they are arranged within the playlist-container. Currently, I am working on imple ...

Ways to incorporate vector .svg images into a D3js tree diagram

var treeData = [ { "name": "Top Level", "parent": "null", "remark":"yes", "children": [ { "name": "Level 2: A", "parent": "Top Level", "remark":"yes", "children": [ { "name": "So ...

Designing CSS elements that flow from top to bottom, left to right, and extend to the right when overflowing

I'm attempting to create a layout where divs are displayed from top to bottom, but once they reach the bottom of the browser window, any additional divs will overflow to the right. You can take a look at the desired layout here: https://i.stack.imgur. ...