primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
8.9k stars 1.1k forks source link

AccordionTab: does not re-render when reactive variable change, sometimes is not rendered at all #4661

Open K4T opened 9 months ago

K4T commented 9 months ago

Describe the bug

I have created a simple carousel, and in each carousel item, I need to display different, dynamic Accordions/AccordionTabs. The problem is that accordions are not re-rendered after I switch slides (update reactive variable responsible for keeping value of currently displayed object in slide). Accordions are correctly rendered only on page load, but they are not updated after a slide change view pressing Next or Prev buttons. I have also noticed that sometimes accordions are not rendered at all...

Can be related to: https://github.com/primefaces/primevue/issues/622

Reproducer

https://stackblitz.com/edit/u1x8yw-tyjpd3?file=src%2FApp.vue

PrimeVue version

3.37.0

Vue version

3.x

Language

ES6

Build / Runtime

Vite

Browser(s)

No response

Steps to reproduce the behavior

  1. Open attached demo
  2. First slide will be rendered on page load with correct data and content (also for accordions)
  3. Click "next" to change the slide - accordion tabs are not being updated

Expected behavior

Accordion tabs should re-render with new content (book).

danluchs commented 8 months ago

We've run into this as well. The Accordion component won't re-render on data updates. The inputs within the Accordion remain reactive, but the component just won't re-render.

We found this solution (hack), based on this article: https://michaelnthiessen.com/force-re-render/#key-changing-to-force-a-component-refresh

Wrote a composable for our Nuxt project (useRenderKey.ts):

import { ref } from 'vue';
// "generateId" generates a random alphanumeric string from our utilities
const { generateId } = useUtilities();
const renderKey = ref(generateId());
function updateRenderKey() {
  renderKey.value = generateId();
}

export default function () {
  return {
    renderKey,
    updateRenderKey
  };
}

Then, in the component:

<script setup>
import { computed } from 'vue';
const { renderKey, updateRenderKey } = useRenderKey();
const panelData = computed(() => {
  // do stuff that generates the AccordionTab's UI data...
  updateRenderKey();
  return ...
});
</script>

<template>
// template stuff here...
<Accordion :key="renderKey">...</Accordion>
// more template stuff...
</template>
tugcekucukoglu commented 7 months ago

Describe the bug

I have created a simple carousel, and in each carousel item, I need to display different, dynamic Accordions/AccordionTabs. The problem is that accordions are not re-rendered after I switch slides (update reactive variable responsible for keeping value of currently displayed object in slide). Accordions are correctly rendered only on page load, but they are not updated after a slide change view pressing Next or Prev buttons. I have also noticed that sometimes accordions are not rendered at all...

Can be related to: #622

Reproducer

https://stackblitz.com/edit/u1x8yw-tyjpd3?file=src%2FApp.vue

PrimeVue version

3.37.0

Vue version

3.x

Language

ES6

Build / Runtime

Vite

Browser(s)

No response

Steps to reproduce the behavior

  1. Open attached demo
  2. First slide will be rendered on page load with correct data and content (also for accordions)
  3. Click "next" to change the slide - accordion tabs are not being updated

Expected behavior

Accordion tabs should re-render with new content (book).

Reproducer link seems working correctly. Am I missing something?

fernandoanael commented 5 months ago

Hello @tugcekucukoglu I encountered a similar issue and spent a day grappling with it before realizing that the AccordionTab wasn't updating.

Interestingly, I was able to reproduce the problem when using a computed property, but it appears that the computed property is not the root cause (as demonstrated in the StackBlitz example).

While it may seem unusual to use a computed property instead of a ref directly, this is a specific use case in our project. Occasionally, a sibling component initiates a change, which in turn triggers alterations in the computed properties within the page.

However, it seems that the issue arises when a function modifies the value of the variable used in v-for.

This example demonstrates the bug: https://stackblitz.com/edit/u1x8yw-xklxes?file=src%2FApp.vue

Right now, the only workaround is using the ref key to force re-render.

JJosephttg commented 2 months ago

I am also experiencing this. You can actually get the above reproduction failing as he expects it to by removing the key from the accordion element, and setting the initial currentItem in the carousel to the first index of the prop array to start. Even with just the key removed, the accordion tabs don't even show up. I think it has to do with the accordion tracking the ref of the set key. Taking it off makes it not track the changes made to the ref

andrejko commented 1 month ago

Experienced same thig, was struggling with content not updated 2 days, until made an experiment placing same output before and inside Accordiron: image