L'utilisation de `this` pour mettre à jour useState dans une fonction pendant la construction entraîne une erreur non définie - Nuxt 3 & Strapi 4.12 - SFC (configuration du script)
P粉436410586
2023-08-03 16:40:32
<p><br /></p><h2><br /></h2>
<p><code>"@strapi/strapi": "4.12.0",</code></p>
<p><code>"nuxt": "^3.6.5",</code></p>
<p>Dans mon environnement de développement, j'ai une page de projets avec un filtre de catégorie qui affiche soit tous les projets, soit les catégories avec les projets correspondants. <br /><br />J'utilise useAsyncQuery pour obtenir des éléments et des catégories de Strapi. <br /><br />Dans le filtre, il y a un menu déroulant avec différentes catégories. Lorsque vous cliquez sur ces catégories, la fonction switchCategory(filter.id) sera appelée. Dans cette fonction, divers états sont mis à jour à l'aide de ceci.<br /><br />请查看以下脚本设置:</p><p><code></code></p>
<pre class="brush:php;toolbar:false;">
importer {projectsQuery} depuis "~/queries/projects/archive" ;
importer { filterQuery } depuis "~/queries/projects/filter" ;
const { data : filterRes } = wait useAsyncQuery (filterQuery)
const { données : projetsRes } = attendre useAsyncQuery (projectsQuery)
var isLoading = useState('isLoading', () => false)
var filterActive = useState('filterActive', () => false)
var filterActiveText = useState('filterActiveText', () => 'Tous les projets')
constprojectsUrl = useState('projectsUrl', () => '/projecten/')
const filters = useState('filters', () => filterRes.value.projectCategories.data)
const projets = useState('projects', () => projetsRes.value.projects.data)
var filteredProjects = useState('filteredProjects', () => projets)
fonction switchCategory(id) {
this.isLoading = vrai
this.filterActive = faux ;
document.getElementById("projects-container").scrollIntoView({
comportement : « doux »,
});
setTimeout(() => {
si (identifiant) {
this.filters.map((élément) => {
si (id == article.id) {
this.filteredProjects = item.attributes.projects.data;
this.filterActiveText = item.attributes.Title;
}
});
} autre {
this.filteredProjects = this.projects;
this.filterActiveText = 'Tous les projets';
}
this.isLoading = faux ;
}, 600)
}</pré>
<p>并且在模板元素中:</p>
<pre class="brush:php;toolbar:false;"><div class="flex flex-col gap-y-8 md:gap-y-24 lg:gap-y-40 transition-toute durée -600 facilité d'entrée et de sortie" :class="{
'flou-0' : !isLoading,
'flou' : isLoading,
}">
<div class="grid md:grid-cols-2 gap-8 md:gap-16 lg:gap-24 relative" v-for="(projet, id) dans filteredProjects" :key="id">
<Nuxt-Link class="absolute inset-0 w-full h-full z-10"
:to="projectsUrl + project.attributes.Slug"></Nuxt-Link>
<div class="flex flex-col items-start justifier-entre">
<div class="sticky top-40 pb-16 lg:pb-20 prose-xl">
<h3 class="text-xl md:text-4xl lg:text-5xl font-bold">{{ project.attributes.Title }}</h3>
<p class="block">{{ project.attributes.Intro }}</p>
</div>
<Button class="flex mb-4" color="light" :to="projectsUrl + project.attributes.Slug">
Projet bekijken
</Bouton>
</div>
<div class="-order-1 md:order-1 relatif">
<div class="aspect-video md:aspect-square lg:aspect-[12/18] relatif">
<Média
:url="projet.attributes.FeaturedImage.data.attributes.url"
:extension="project.attributes.FeaturedImage.data.attributes.ext"
/>
</div>
</div>
</div>
</div></pré>
<p>Lorsque je construis le projet, j'utilise nuxt build, puis j'utilise node .output/server/index.mjs pour démarrer un serveur Node, le projet peut se charger normalement. Mais lorsque j'essaie de filtrer, tout en essayant de mettre à jour des variables telles que isLoading et filterActive dans la fonction switchCategory, l'erreur est renvoyée : TypeError : Impossible de définir les propriétés d'undéfini (réglage de "isLoading"). <br /><br />Tentative de correction n°1<br /><br />Je pensais que, peut-être qu'après la construction, il ne comprend pas ce contexte (car lorsque j'essaie de console.log , ceci n'est pas non plus défini). J'ai donc essayé de refactoriser le code, comme ceci : ;
<pre class="brush:php;toolbar:false;">const switchCategory = (id) =>
isLoading = vrai
filtreActive = faux ;
document.getElementById("projects-container").scrollIntoView({
comportement : « doux »,
});
setTimeout(() => {
if (id && filtres) {
filtres && filtres.value.map((élément) => {
si (id == article.id) {
filteredProjects = item.attributes.projects.data;
filterActiveText = item.attributes.Title;
}
});
} autre {
filteredProjects = projets ;
filterActiveText = 'Tous les projets';
}
isLoading = faux ;
}, 600)
}</pré>
<p>J'ai changé la fonction normale en fonction de flèche et je l'ai supprimée. <br /><br />Dans setTimeout, j'ai dû changer filters.map en filters.value.map (je ne sais pas vraiment pourquoi le format a changé). <br /><br />Maintenant, le code fonctionne correctement (pas d'erreur), mais il ne met pas à jour le DOM de la boucle d'élément dans le modèle. <br /><br />Tentative de correction n°2<br /><br />Après avoir cherché et débogué pendant un certain temps, j'ai trouvé le contenu de DefineExpose dans la documentation de Vue. <br /><br />Il mentionne que les paramètres du script sont "fermés" par défaut. J'ai (désespérément) ajouté ceci aux paramètres de mon script, y compris toutes les variables : </p><p><code></code><em></em></p> ;
<pre class="brush:php;toolbar:false;">defineExpose({
filtreRes,
projetsRes,
pageRes,
est en cours de chargement,
filtreActive,
filtreActiveText,
URL des projets,
des filtres,
projets,
Projets filtrés,
})</pré>
<p>Malheureusement, comme prévu, cela n’a pas fonctionné comme par magie. <br /><br />Solution ? <br />Je vois probablement les choses dans le mauvais sens, mais je ne vois aucune autre solution.<br /><br />Est-ce que j'ai raté quelque chose ? </p><p><br /></p>
Je ne suis pas sûr de pouvoir fournir un extrait de code fonctionnel complet, mais je peux peut-être vous guider vers une solution.
useState n'est disponible que lors de la construction ou lorsque le composant est rendu. Ainsi, modifier les paramètres de la requête après le rendu ne la mettra pas à jour. Peut-être que restituer le composant après un changement d'état serait utile ?