Skip to content

React – how to remove scroll listener

In Home Components, if you scroll down, you will see the Console log something. It’s because

      .on("progress", function (e) {
        console.log(e.progress);
      });

Which is Scroll Listener.

The problem is that when I switch to other pages such as /about or /dashboard, the Console still log when scrolling because of console.log(e.progress);, which I want to get rid of when I switch to other pages.

How can I remove the scroll listener when I switch to other pages?

Example.js

import React, { useEffect } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import ScrollMagic from "scrollmagic";

export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  useEffect(() => {
    const scrollController = new ScrollMagic.Controller({
      globalSceneOptions: { triggerHook: "onCenter" }
    });
    const scrollScene = new ScrollMagic.Scene({
      triggerElement: "#pin",
      duration: 2000,
      offset: -50
    })
      .setPin("#pin")
      .on("progress", function (e) {
        console.log(e.progress);
      });
    scrollScene.addTo(scrollController);
  }, []);
  return (
    <React.Fragment id="pin">
      <h2>Home</h2>
      <div style={{ height: "1700px" }}>Another Stuff</div>
    </React.Fragment>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
      <div style={{ height: "1700px" }}>Another Stuff in About</div>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
      <div style={{ height: "1700px" }}>Another Stuff in Dashboard</div>
    </div>
  );
}

Codesandbox
https://codesandbox.io/s/react-router-basic-forked-tt953?file=/example.js

Answer

In the cleanup of the useEffect add scrollController.removeScene(scrollScene);

  useEffect(() => {
    let scrollController = new ScrollMagic.Controller({
      globalSceneOptions: { triggerHook: "onCenter" }
    });
    let scrollScene = new ScrollMagic.Scene({
      triggerElement: "#pin",
      duration: 2000,
      offset: -50
    })
      .setPin("#pin")
      .on("progress", function (e) {
        console.log(e.progress);
      });
    scrollScene.addTo(scrollController);

    return () => {
      console.log("unmount");
      scrollController.removeScene(scrollScene);
    };
  }, []);

Note: the only attribute that can be passed to React.Fragment is key. ReactFragment docs .

When I tried this code sandbox it wasn’t always working, but when i downloaded the code and ran it on my browser it worked. Not sure why.