J'ai un composant réutilisable qui est un lecteur vidéo video.js. Ce composant fonctionne correctement lorsque les données sont transmises lors du chargement initial du DOM.
Je dois comprendre pourquoi mon composant n'est pas re-rendu après la mise à jour de l'état dans Vuex.
Le composant Parent transmet les données de la vidéo via des accessoires. J'ai également cet ensemble pour être utilisé avec plusieurs vidéos et cela fonctionne bien avec un seul ou plusieurs.
<div v-for="video in videos" :key="video.id">
<video-player :videoName="video.videoName" :videoURL="video.videoURL" :thumbnail="video.thumbnail"></video-player>
</div>
Je règle l'état initial sur une vidéo générique pour tous les utilisateurs de mon magasin Vuex.
getFreeVideo: [
{
videoName: "the_video_name",
videoURL: "https://demo-video-url.mp4",
thumbnail: "https://s3.amazonaws.com/../demo-video-poster.jpg"
}
]
Ceci est défini dans les données dans videos
(et plus tard à getFreeVideo)}
data () {
return {
videos: []
}
}
Je mets videos
dans data () pour obtenirFreeVideo dans le magasin au cours du cycle de vie created ():
this.videos = this.getFreeVideo
..et vérifier si un utilisateur a une vidéo personnelle et mettre à jour l'état dans le cycle de vie created ().
this.$store.dispatch('getFreeVideo', 'the_video_name')
Cela fait une demande avec axios et renvoie nos données vidéo avec succès.
J'utilise mapState import { mapState } from 'vuex
pour surveiller un changement d'état.
computed: {
...mapState(['getFreeVideo'])
}
Je ne vois pas pourquoi this.videos n'est pas mis à jour. Ici, mon hypothèse concernant le comportement attendu serait que les vidéos [] soient mises à jour à partir du changement d'état et d'un re-rendu du composant.
Comme vous pouvez le voir ci-dessous, l'état a été mis à jour et la méthode videoUpdate () dans les propriétés calculées contient également les nouvelles données:
..mais les vidéos [] n'étant jamais mises à jour, le composant vidéo ne reçoit jamais les accessoires, les nouveaux accessoires, etc.
Quelques notes:
TypeError: Cannot read property '_withTask' of undefined
, mais cela se produit même lorsque la vidéo de démonstration est chargée correctement. Cela ne semble donc pas être lié et je ne trouve rien ici qui se présente comme indéfini.TL; DR
En gros, je ne parviens pas à rendre le composant enfant après le changement d'état. Et bien que je puisse obtenir les données dans videos[]
avec une structure différente, elles ne sont toujours pas restituées.
Pourquoi les données ne parviennent-elles pas à passer au travers, et la restitution n’arrive-t-elle jamais?
_ {Merci de ne pas poster de réponses qui ne contiennent que des liens vers 'comprendre la réactivité' ou quelque chose sans explication.} ????
ajouté pour @acdcjunior
//action
getFreeVideo: (context, videoName) => {
axios({
method: 'post',
url: 'https://hidden-for-posting',
data: {
action: 'getVideo',
userId: '1777', // (hardcoded to test)
videoName: videoName
},
headers: {
'x-api-key': apiKey,
'Content-Type': 'application/json'
}
})
.then(response => {
let video = [
{
videoName: response.data.videoName,
videoURL: response.data.videoURLs.mp4,
thumbnail: response.data.thumbnails['1280']
}
]
return context.commit('updateGetFreeVideo', video)
})
.catch(error => {
if (error.response) {
console.log(error.response)
} else if (error.request) {
console.log(error.request)
} else {
console.log('Error', error.message)
}
console.log(error.config)
})
}
// mutation:
updateGetFreeVideo: (state, payload) => {
return state.getFreeVideo = payload
}
// getter:
getFreeVideo: state => {
return state.getFreeVideo
}
Sur la base du code que vous avez posté, en considérant le modèle:
<div v-for="video in videos" :key="video.id">
Il choisit la videos
parmi:
data () {
return {
videos: freeVideo
}
}
Bien qu'il soit initialisé à partir de freeVideo
, nulle part dans votre code, vous affichez une update de videos
.
Solution:
Vous avez déjà l'état mappé dans la getFreeVideo
calculée:
computed: {
...mapState(['getFreeVideo'])
}
Utilise le:
<div v-for="video in getFreeVideo" :key="video.id">
Je mets
videos
dans data () pour obtenirFreeVideo dans le magasin au sein du fichier cycle de vie created ():this.videos = this.getFreeVideo
Ce n'est pas suffisant pour garder this.videos
mis à jour avec quoi que ce soit this.getFreeVideo
. Chaque fois que quelque chose est défini sur this.getFreeVideo
, il ne fera que changer this.getFreeVideo
, pas this.videos
.
Si vous souhaitez mettre à jour automatiquement this.videos
chaque fois que this.getFreeVideo
change, créez un observateur:
watch: {
getFreeVideo() {
this.videos = this.getFreeVideo
}
}
Et continuez à utiliser videos
dans le v-for
:
<div v-for="video in videos" :key="video.id">
Si la propriété calculée n'est pas référencée (par exemple, "utilisé"), votre vue de code de modèle ignorera la réactivité correspondante.
Tout d'abord, la structure du magasin et les propriétés de l'état sont un peu confuses.
Je voudrais:
1) Avoir une propriété "vidéos" dans l'état du magasin
2) Initialisez-le comme un tableau vide
3) Au démarrage de l'application, remplissez-le correctement avec les valeurs par défaut "load", avec une mutation qui lui applique la vidéo "par défaut"
4) Ayez les composants mapGetter
sous le nom de videos
5) Chaque fois que vous chargez un composant qui "met à jour" les vidéos possibles, envoyez l'action et appelez la mutation appropriée pour remplacer la propriété "vidéos" du magasin.
Remarque: Si les composants peuvent avoir différentes vidéos "par défaut", vous souhaiterez probablement avoir une propriété videos
dans le magasin initialisé avec false
. Cela vous permet ensuite d’avoir une propriété calculée qui utilise le getter pour la propriété videos
dans le magasin et s’il est false
Ce que je veux dire, c'est, pour le premier cas
// store
state: {
videos: []
}
getters: {
videos(state) { return state.videos }
}
//components
...
computed: {
videos() {
this.$store.getters.videos
}
}
For the second case
// store
state: {
videos: false
}
getters: { personal_videos(state) { return state.videos } }
//components
data() { return { default: default_videos } },
computed: {
...mapGetters([ 'personal_videos' ]),
videos() {
if (this.personal_videos) {
return this.personal_videos
} else {
return this.default
}
}
}
Personnel: donnez-leur de meilleurs noms -_- et la première option est la plus claire.
En fin de compte, tout le problème était avec video.js. Je suis à moitié tenté de supprimer cette question, mais je ne voudrais pas que quiconque aide à perdre des points.
La solution et l'entrée ici ont aidé à repenser mon utilisation des observateurs ou la façon dont j'essayais de le faire. Pour l’instant, j’ai juste utilisé le magasin central car cela fonctionne bien, mais cela devra être refait ultérieurement.
Je devais renoncer à utiliser video.js en tant que lecteur pour le moment, et un lecteur vidéo html5 standard fonctionne sans problème.