Search code examples
vue.jsvuejs3vue-reactivity

Vue 3 re-render every row again after one value change problem


I'm encountering an issue with re-rendering values in a large table within a substantial application. For simplicity's sake, I've abstracted just the essential elements in a Vue playground (This simplified version doesn't make much sense - it serves purely for illustrative purposes.)

Here's the situation:

I have a table where rows are generated from some data, with values returned by a function. The problem arises when I change a single value in one row - every 'grade' value in every row gets updated.

I understand that Vue probably executes the v-for loop again, which then runs everything on every row, including all functions. However, is there a way to ensure only the row I've modified is re-rendered? Something similar to what the :key directive does.

As I've mentioned, the original table is a significantly larger component within a substantial project, and the function returning a value is necessary. While I could potentially pre-compile data into some object, the performance issue remains the same - it would still need to fetch the correct data for every value (which could number in the thousands).

(every run of function get_grade prints "ajaj" to console)

Here is the very-simplified table in Vue playground

enter image description here


Solution

  • The v-memo directive is made specifically for this. You pass in an array with expressions, which are evaluated for the component and the values are stored internally. Before rendering, the expressions are evaluated again, and the component will only be updated if at least one of the values changed.

    So in your example, you just have to track the current grade:

    <tr v-for="pupil of the_class" v-memo="[pupil.grade]">
    

    Now the row will only be re-rendered when the grade has changed after the last render.

    Here is the updated playground