Search code examples
reactjsreactstrapreact-functional-component

onClick event not firing on functional element


For the life of me I cannot understand why the click event is not firing in my functional component.

Here's my component:

import React, { useState, useEffect } from 'react';
import {
    Collapse,
    Navbar,
    NavbarToggler,
    Nav,
    NavItem,
    NavLink,
} from 'reactstrap';

import classNames from 'classnames';
import img from '../../img/logo/logo-white.svg';

const NavBar = () => {
    const [isOpen, setIsOpen] = useState(false);
    const toggle = () => {
        console.log('toggllling', isOpen);
        setIsOpen(!isOpen);
    };

    return (
        <div
            id="nav-wrap"
            className={classNames({ 'bg-dark-blue': isOpen })}
        >
            <Navbar color="transparent" dark expand="lg" className="container">
                <a className="navbar-brand" href="/">
                    <img alt="logo light" src={img} />
                </a>
                <NavbarToggler onClick={toggle} />
                <Collapse isOpen={isOpen} navbar>
                    <Nav className="navbar-nav" navbar>
                        <NavItem className="active">
                            <NavLink href="/">First</NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink href="/">second</NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink href="/">Thord</NavLink>
                        </NavItem>
                        <NavItem className="separated">
                            <NavLink href="/">Fourth</NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink href="/">fifth</NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink href="/" className="btn btn-light">last</NavLink>
                        </NavItem>
                    </Nav>
                </Collapse>
            </Navbar>
        </div>
    );
};

export default NavBar;

It's a bit more advanced version of the navbar toggle example from the reactstrap page: https://reactstrap.github.io/components/navbar/

I can see from the React Devtools that the event is bound to the correct react component. If I replace toggle with something that should fire immediately like a function call, then it fires immediately. Yet when I click on the actual button, nothing happens. I even bound a click event to the document to see if there is something hidden above the button and logged out if the event propagates down to correct element - it did. so for the life of me, I cannot figure out why the toggle function never fires and why I never see 'toggllling' in my console. I've tried adding this onClick to any of the other elements in the component also - and it never works anywhere inside the component.

It's probably something really small, that I'm missing here, but for the life of me - I cannot figure out what it is exactly. Not sure what other bits of information could be useful here. Perhaps how I use the component:

ready(() => {
    // Example:
    const wrap = document.getElementById('nav-wrap');
    if (wrap) {
        // perform element replacement
        const parent = wrap.parentNode;
        const temp = document.createElement('div');
        render(<NavBar element={wrap} />, temp);
        parent.replaceChild(temp.querySelector('div#nav-wrap'), wrap);
    }
});

Edit:

I simplified the component and results are the same - the event is not firing. When I debug it with browser devtools and add breakpoint at mouse click, then I can see that function call ends up in react-dom.development.js function noop() {} Why is that?


Solution

  • Not sure how useful this answer is to the general population. There are not of onClick "not working" questions. Mods - if you see nothing to learn here, please just mark the question for deletion.

    So what happened here was that I had this bit of a relic replacement mechanic in my index.js which created the component. I rendered the component inside element not in DOM:

            const temp = document.createElement('div');
            render(<NavBar element={wrap} />, temp);
    

    And then looked it up and replaced its pure HTML predecessor with the react component. I went for this complex solution, because initially, I just tried to reuse some components. I later changed this logic, but did not go back to just using render(<NavBar/>, wrap);, which would have saved me all the trouble of writing this question.

    So my own complexity, which I did not reduce on time, created even more overhead and wasted time. So yeah - avoid complexity. That's the lesson here.