Encountered a challenge with vue.js and seeking guidance on the best approach to address it. Here's a concise summary of the issue:
Situation
Data is fetched from a rest API, handled by a class called DataLoader
using javascript prototype syntax. The loaded data usually appears in repetitive formats like lists or cards. To simplify this process, a new component named DataLoaderWrapper
was created, which takes a DataLoader
object as a property. This wrapper displays loading spinners based on the loading state of the DataLoader
, and includes a tag:
<slot :dataLoader='dataLoader' />
To access the data easily, the component can be used as follows:
<DataLoaderWrapper :dataLoader="myDataLoader">
<template slot-scope="props">
<template v-for="item in props.dataLoader.data">
{{item}}
</template>
</template>
</DataLoaderWrapper>
Now, why do we use props.dataLoader
instead of myDataLoader
inside the template? This allows for direct access to dynamically generated DataLoader objects via component bound properties.
Expanding on this concept, consider having a DataLoader
set up to load music releases:
<DataLoaderWrapper :dataLoader="myReleaseLoader">
...
</DataLoaderWrapper>
Each release is associated with one or more artists, requiring separate loading. An extension of the example would look something like:
<DataLoaderWrapper :dataLoader="myReleaseLoader">
<template slot-scope="props">
<template v-for="release in props.dataLoader.data">
<h1>{{ release.Title }}</h1>
Artists:
<DataLoaderWrapper :dataLoader="getArtistsLoader(release)">
<template slot-scope="nestedProps">
{{nestedProps.dataLoader.data.map(artist => artist.Name).join(', ')}}
</template>
</DataLoaderWrapper>
</template>
</template>
</DataLoaderWrapper>
The Problem
While releases load correctly and templates render as expected, new DataLoader instances are created dynamically to load artists for each release. However, the nestedProps
variable fails to update once the DataLoader finishes loading the artist data.
After spending two days debugging, I'm certain that the data is successfully loaded but the spinner persists in the DataLoaderWrapper component. Checking nestedProps.dataLoader
reveals data: []
, which contradicts the component's displayed state. This issue might stem from Vue bindings being one-directional, where a child component update does not trigger a parent update.
A local instance with 'hot-reloading' updates UI changes without a full page reload when files are saved, resulting in different loader states during navigation. Since the cache implemented in the getArtistsLoader(..)
function returns the same loader for a given release, the existing data reappears during UI updates. Attempts with computed properties, direct loader access, and adjusting property references failed to resolve the issue.
Any suggestions on how to tackle this challenge?