How to change background video on scroll in React?

838 Views Asked by At

I am trying to change background video on scroll, using react-intersection-observer. When inView changes to true, useEffect must change state to sample2, and send new video to startscreen, where it's using as background video with position fixed. State is changing, but video is still the same.

//Startscreen

    const Startscreen = ({ sample }) => {
console.log(sample);
      return (
          <video className="videoTag" autoPlay loop muted>
            <source src={sample} type="video/mp4" />
          </video>
      );
    };

//App.js

import sample1 from "./videos/0.mov";
import sample2 from "./videos/2.mov";

function App() {
  const [state, setState] = useState(sample1);
  const { ref, inView, entry } = useInView({
    threshold: 0.5,
  });

  useEffect(() => {
    if (inView === true) {
      setState(sample2);
    } else {
      setState(sample1);
    }
    console.log(state);
  }, [inView]);

  return (
    <div className="App">
      <Startscreen sample={state} />
      <div ref={ref}>
        <AboutMe> 
    </div>
    </div>
)};
1

There are 1 best solutions below

6
On BEST ANSWER

When you change the source of a video, the <video/> element doesn't reload, as explained in this answer : https://stackoverflow.com/a/47382850.

One fix would be

  return (
      <video key={sample} className="videoTag" autoPlay loop muted>
        <source src={sample} type="video/mp4" />
      </video>
  );

Some notes on your App implementation

You don't need the useEffect at all since your component will re-render when inView changes. So you don't actually need a state at all because you can compute your sample from inView. Try this instead:

function App() {
  const { ref, inView, entry } = useInView({
    threshold: 0.5,
  });
  const sample = inView ? sample2 : sample1;
  console.log(sample);

  return (
    <div className="App">
      <Startscreen sample={sample} />
      <div ref={ref}>
        <AboutMe> 
      </div>
    </div>
)};

Also please note that in your original code, when you are calling console.log(state);, you are actually calling your previous state value, not the state value that you have just set.

Indeed, if your state is sample1, calling setState(sample2); then console.log(state); will print sample1. state will equal sample2 after the next re-render caused by this setState, but you are not logging on each render, only when inView changes. You can manage to also log the new state in the re-rendering by adding state to useEffect dependency array:

useEffect(() => {
    if (inView === true) {
      setState(sample2);
    } else {
      setState(sample1);
    }
    console.log(state);
  }, [inView, state]);