React context state updates are always one step behind

  javascript, reactjs

I have read questions with similar titles and they have not solved my problem.

I have an API call whose result needs to be shared amongst several components. The parent component makes the call and React’s context is used to share it amongst the child components:

MainPage.js:

import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { VideoPlayer } from "../components/VideoPlayer";
import VideoContext from "../components/VideoContext";


export default function Watch() {
    const [video, setVideo] = useState({});
    const { videoHash } = useParams();
    const [isLoading, setIsLoading] = useState(true);

    useEffect(() => {
        setIsLoading(true);
        getVideo();
    }, [videoHash]);

    const getVideo = async () => {
        if(videoHash) {
            const res = await getVideoFromApi();
            setIsLoading(false);
            setVideo(res.video);
        }
    };

    return (
        <>
            {isLoading ? (
                <div>Loading...</div>
            ) : (
                <VideoContext.Provider value={{ video, setVideo }}>
                    <VideoPlayer videoHash={videoHash} />
                </VideoContext.Provider>
            )}
        </>
    );
}

VideoPlayer.js:

import React, { useState, useEffect, useContext } from "react";
import VideoContext from "./VideoContext";
import styles from "./VideoPlayer.module.css";

export function VideoPlayer({ videoHash }) {
    const { video, setVideo } = useContext(VideoContext);
    const [forceRender, setforceRender] = useState(true);

    useEffect(() => {
        // I tried adding this to no effect
        setforceRender(!forceRender);
    }, [videoHash]);

    return (
        <video controls className={styles["video-player"]}>
            <source src={video.VideoUrl} type="video/mp4" />
                Sorry, your browser does not support embedded videos.
        </video>
    );
}

VideoContext.js:

import { createContext } from "react";

export default createContext({
    video: {}, 
    setVideo: () => {}
});

It works when the page loads, but when my Link components change the videoHash property the new video loads (I can see when I console.log() the API call) but it does not update in the video player.

The second time a link is clicked and the videoHash param is changed, the video displays but it’s for the previous video.

Source: Ask Javascript Questions

One Reply to “React context state updates are always one step behind”

LEAVE A COMMENT