2
\$\begingroup\$

I have a video component passing data from an async GET request to a child component:

// Inside a v-for loop
<video
    :title="video.title"
    :id="video._uid"
>
// ...
<Controls :videoData="video" />

When receiving the prop in Controls I then use that data to select the video by it's id in the DOM and set data properties according to that element:

created() {
    setTimeout(() => {
        this.video = document.getElementById(this.videoData._uid);
        this.videoDuration = this.video.duration;

        setInterval(() => {
            this.videoCurrentTime = this.video.currentTime;
            this.videoPlaying = !this.video.paused;
            this.videoVolume = this.video.volume;
        }, 1);
    }, 1000);
}

The setTimeout is to get around the data being asynchronous and the setInterval is to continuously update the data, such as the current time of the video, whether it's paused or not, etc.

It works exactly as it should, but it seems really inefficient. What if someone has slow internet and it takes longer than 1000ms to fetch the data, for example.

I would think the fact it's in a v-for loop would prevent the need for setTimeout as the component wouldn't exist before the video has been fetched. I must be missing something.

Request:

created() {
    this.fetchVersion().then(async () => {
        await Axios.get(
            `https://api.storyblok.com/v1/cdn/stories/videos?version=published&token=<STORYBLOK_TOKEN>&cv=${this.getVersion}`
        ).then(res => {
            res.data.story.content.body.forEach(i => {
                this.storyblokVideos.push(i);
            });
        });
    });
}

Does anyone have a better way of making the data reactive?

UPDATE

Thanks to @potato's answer:

I set a data property called isLoading: true then used the video's event oncanplay to conditionally load the controls: @canplay="isLoading = false". No more async errors. Then I used the different events to pass data:

@play="playing = true"
@pause="playing = false"
@timeupdate="updateCurrentTime()"
@volumechange="updateVolume()"

Much more efficient.

\$\endgroup\$
2
\$\begingroup\$

Use events and callbacks to react to things as they happen instead of repeatedly checking for changes.

You can use the .then function to do whatever needs to be done once the data is received.

You can learn about the <video> element events here: https://www.w3schools.com/tags/ref_av_dom.asp

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Good spot! Can always rely on a potato. I'll update my question to reference your answer \$\endgroup\$ – Daniel_Knights Jul 5 '20 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.