VueJS: Issue with `v-for` not displaying components

I have a Todo application built in Vue that may seem slightly overwhelming. Here's the link to the repository: https://github.com/jaiko86/subtasks

All the todo items are managed within the following store structure:

export default {
  state: {
    workspaceIds: [], // IDs of workspaces
    tasksById: {}, // This is where all the tasks are stored
    detachedTask: null,
    focusedTaskId: null,
    currentWorkspaceId: null,
  },
  ...
}

Within the App.vue file, there is a computed property that runs through the tasks as defined by the v-for:

  computed: {
    taskIds() {
      const { currentWorkspaceId, tasksById } = this.$store.state;
      if (this.showOnlyLeafSubTasks) {
        return Object.values(tasksById)
          .filter(task => !task.subTaskIds.length)
          .map(task => task.id);
      } else if (currentWorkspaceId) {
        return tasksById[currentWorkspaceId].subTaskIds;
      }
    },
  },

This computed property filters and returns a list of relevant tasks based on specific conditions like the current workspace. Each task has a unique ID formatted as task-#, with its input placeholder displaying the task ID.

The template in App.vue includes:

<template>
  <div id="app">
    <!-- Workspace Navigation -->
    <WorkspaceNav /> 

    <!-- Content Display -->
    <TaskWrapper v-for="id in taskIds" :key="id" :id="id" :depth="0" />

    <!-- Additional Filters -->
    <TaskFilters />
  </div>
</template>

However, there seems to be an issue with rendering the items returned by the computed property.

Despite the console showing the correct data, and the Vue dev tool indicating the expected output, the view itself displays incorrect results.

For better visualization: https://i.sstatic.net/1sc5a.png

VUE Dev Tool Snapshot: https://i.sstatic.net/l5537.png

Console Output after selecting the <App> component in the dev tool:

"["task-1", "task-2"]"

A custom function for hierarchical printing has been implemented:

> printTree()
task-0
  task-1

  task-2

The DOM structure related to the code snippet in question looks something like this:


    <div id="app">
      <div class="workspace-nav">
        ...
      </div>
      <div data-v-76850a4a="" data-v-7ba5bd90="" class="leaf">
        <div data-v-76850a4a="" class="main-task depth-0">
          <!---->
          <div class="progress-indicator">
            <div class="checkmark gray-checkmark"></div>
          </div>
          <input placeholder="task-1" />
        </div>
        <div class="sub-tasks"></div>
      </div>
      <div class="filters">
        ...
      </div>
    </div>

Despite having two items in the taskIds array, only one item is being rendered visibly, causing confusion and discrepancy between the actual data and its representation.

Answer №1

Here's a potential explanation...

When the computed property returns its array, it may only contain one item initially. This can be verified in various ways, such as adding the following to your template:

{{ taskIds }}

Although the array could later change to have two items, if these changes do not trigger reactivity, the re-rendering will not occur.

The most likely scenario is that tasksIds is returning

tasksById[currentWorkspaceId].subTaskIds
. This leaves two possibilities - either subTasksIds is not reactive, or it is being modified in a way that does not trigger reactivity (e.g. direct index modification).

Upon review of your store code, no obvious examples of the latter stand out. However, this line from createTask seems suspiciously like the former:

state.tasksById[task.id] = task;

This code adds task to an existing object under a potentially new key. It aligns with one of the reactivity caveats - you cannot directly add new properties to objects:

https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

To address this, you should utilize Vue.set:

Vue.set(state.tasksById, task.id, task);

To gain better insights into what's happening, consider adding the following logging at the end of createTask:

console.log(state.tasksById);

By examining the objects/arrays in the console, you should find evidence of the Vue reactivity system. Reactivity will manifest as references to Observer, with properties having getters and setters that require clicking to view values. Directly added tasks without Vue.set will simply appear as regular objects/arrays. Understanding this distinction can greatly facilitate debugging such issues in the future.

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

How can I manage file input within a Vue.js application?

After attempting to open a file input with a button, I encountered an issue. When clicking the button, the client reported: “this.$refs.image.click”. Below is my code snippet: <v-btn height="50" ...

You are unable to call upon an object that may be undefined

I am using TypeScript in conjunction with React, and I keep encountering an error message. Cannot invoke an object which is possibly 'undefined'.ts(2722) const onChange: ((...args: any[]) => any) | undefined The errors occur in the following ...

What is the process for verifying your identity with Google OAuth2 in Vue.js?

Being new to vue.js, I have been struggling with a particular issue for days. Despite knowing that there are a few plugins available, such as: vue-google-auth and vue-google-signin-button and vue-authenticate Unfortunately, none of these plugins come ...

Unable to retrieve href attribute from <a> tag using jQuery

I am attempting to retrieve the href link from an <a> tag in a Laravel 5.2 view (blade), but it keeps displaying as undefined. I'm not sure what is causing this issue with the code. Any assistance would be greatly appreciated! Below is the snip ...

Choose an option within a row of a table

Is there a way to display the div element with the .mynote class when clicking on the input that has an id of title? I attempted the code below, however, it does not seem to be functioning as expected. $("#title").click(function() { $(".mynote").show( ...

Converting JSON into TypeScript class or interface?

Currently, I am in the process of building a web application using Angular2 and Typescript. The JSON structure I have is as follows: { "homeMenu":{ "aname1":{ "title":"text", "route":"myroute" }, "aname2":{ "title":"tex ...

Assistance with utilizing Regular Expressions to extract the className from a React/JSX component

For instance, I have <img className='class' src='somelink' /> and my goal is to extract only the className='class'. I have already attempted using / className='.+'[ |>] while going through files in search of ...

Is there a way to invoke a high-order function multiple times within the code?

const x = { a:1 }; (function q({a}){ console.log(a); return a; })(x); // unable to execute console.log(q(x)) I'm encountering an issue trying to run line 6. Why is this happening? The console works in line 3 when I remove line 6: Error: q is n ...

The issue with Vue email validation not functioning correctly when the div ID is removed

I'm completely new to Vue.js and I'm keen on understanding why removing the div with id "app" in this codepen example (not mine) leads to the failure of rendering the email validator input field. <div class="container" id="app&q ...

Achieving resolution of promised information

Upon reviewing the code snippet provided, it can be seen that: function one(){ var prm = new Promise(function(resolve,reject){ resolve("one"); }); prm.customKey = function(){ } return prm; } function two(){ var prm = one(); ...

Tips for correctly mapping a shuffled array in React/Next without triggering a hydration mismatch error

I've been working on a Next.js website and I'm trying to display a randomized list of famous quotes. To achieve this, I'm using lodash to shuffle the array of quotes and then mapping them onto the page. import { useMemo } from 'react&ap ...

Issue with Axios API call causing incomplete array response storage in variable

Utilizing Axios to retrieve data from an API and store it in an empty variable has proven challenging. Despite my efforts, I have not been successful in saving the entire API call result into the variable. export default createStore({ state: { apiUrl ...

Transforming a React object into an array and displaying it on the frontend using the .map method

After making a single API call, I have received two different sets of data. The first set is an array containing information about various items, including their names, prices, rarity, and images. The second set consists of items with details such as condi ...

What is the proper way to transfer data from a file using npm's request package?

I'm currently utilizing npm's request module to interact with an API. The API specifications require that data be sent through a file using the @site.json notation when making a CURL request. For example: curl -X POST -d @site.json 'https ...

Leverage the redux state within a functional component exported from a React function

I need to create an array from my current redux state using an exported function within a functional component. The goal is to utilize my useSelector data and dispatch function within this function. However, I only require the generate function to be calle ...

The authentication process for the Google YouTube API encountered an error due to a bad request and an invalid

Encountering issues with logging into the Google YouTube API due to bad request and an invalid Key. Despite renewing my credentials multiple times on the Google console. Changed the API key several times but the problem persists. The code I am currently ...

Play Youtube Video Automatically When Scrolled to

Is it possible to have a Youtube video start playing automatically when you reach it on the page? I did some research online and found methods for the old Youtube embed code, but I'm looking for a more current solution. Does anyone know how to make Yo ...

Can the ES2016 Proxy be used to intercept the "typeof" operation?

Can a handler property be defined to intercept typeof proxyObject? It is not mentioned in any of the traps listed on Mozilla. ...

Implementing jQuery's live() method to handle the image onload event: a guide

Looking to execute a piece of code once an image has finished loading? Want to achieve this in a non-intrusive manner, without inline scripting? Specifically interested in using jQuery's live() function for dynamically loaded images. I've attemp ...

The incompatibility of proxy objects and Object.create explained

Whenever I attempt the code below, I consistently receive a "RangeError: Maximum call stack size exceeded" error. However, if I simply access the receiver without including console.log(receiver);, everything works fine. This situation is very confusing. c ...