0

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>
)};
Andrew Kruglik
  • 182
  • 1
  • 11

1 Answers1

2

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]);
Ricola
  • 2,621
  • 12
  • 22
  • Good example of overthinking, but it's still not working. I put console.log(props.sample) in Startscreen component, it shows that it changes, but video is still the same. I even tried to add state in Startscreen, but no result - Startscreen component don't want to re-render with new prop. – Andrew Kruglik Jun 12 '21 at 17:23
  • "I put console.log(props.sample) in Startscreen component, it shows that it changes, but video is still the same." => Then if the state changes in Startscreen but the video stays the same, I believe your issue is not in App, but in Startscreen itself, but you haven't shared the code for Startscreen. – Ricola Jun 12 '21 at 17:28
  • Check again the first part, above App.js – Andrew Kruglik Jun 12 '21 at 17:31
  • Ok, now with these details, I can tell that the issue is in the ` – Ricola Jun 12 '21 at 17:58
  • 1
    I've just realesed that you may be offended with my words about overthinking - do not take personally, I was talking about myself) Your code is working great, thank you very much! One more question: why is it necessary to add key attribute? Can't find any information about it – Andrew Kruglik Jun 13 '21 at 01:05
  • No offence taken :-) As for the key attribute, there are some explanations at the bottom of this answer : https://stackoverflow.com/questions/41303012/updating-source-url-on-html5-video-with-react/47382850#47382850 I personally don't know much more about it. – Ricola Jun 14 '21 at 08:21