Daar44
Daar44

Reputation: 469

React addEventListener handler function called TWICE

Having such simple React main App file:

import React from 'react';
import './App.css';

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

import {Header} from "./Components/header"
import {Footer} from "./Components/footer"
import {Sidebar} from "./Components/sidebar"
import {About} from "./Components/about"
import {User} from "./Components/user"

const listener = () => {
    console.log("Main listener")
};

function App() {

    const media = window.matchMedia('(min-width: 700px)');
    media.addEventListener("change", listener);

    return (
        <Router>
            <div className="App">

                <Header />
                <Sidebar />
                <Footer />

                <Routes>
                    <Route path="/"></Route>
                    <Route path="/about" element={<About/>}></Route>
                    <Route path="/user" element={<User/>}></Route>
                </Routes>

                <div className="App">
                    <ul>
                    <li>
                        <Link to="/">Home</Link>
                    </li>
                    <li>
                        <Link to="/about">About</Link>
                    </li>
                    <li>
                        <Link to="/user">User</Link>
                    </li>
                    </ul>
                </div>

            </div>
        </Router>
    );
}

export default App;

The thing that makes me wonder is that the change event handler function (listener) is called TWICE! when I resize the browser window. Why isn't the handler function called just once as expected?

Upvotes: 1

Views: 1666

Answers (1)

Amila Senadheera
Amila Senadheera

Reputation: 13245

You cannot expect App to be called only once. It will be called in every rerender (by React renderer when it wants to).

Normally, event listers are added when the component is mounted and they are removed when the component is getting unmounted to avoid possible memory leaks.

It can be done using a useEffect as below.

import React, { useEffect } from "react";
...
...

const listener = () => {
    console.log("Main listener");
};

function App() {
    useEffect(() => {
        const media = window.matchMedia("(min-width: 700px)");

        // add the event listener
        media.addEventListener("change", listener);
        
        return () => {
            // remove the event listener
            media.removeEventListener("change", listener);
        };
    }, []);

    return (
        ...
        ...
    );
}

export default App;

Upvotes: 1

Related Questions