I need help getting this event handler to work in React

Problem
I’m trying to wrap my mind around event handling in react. In this object, I want to return 'clicked intro' to the console. What am I missing?

My next issue is how can I reuse the same handler when clicking different links but passing different parameters for each link?

The Code

class NavPanel extends Component {
    constructor(props) {
        super(props);
        this.navHandler = this.navHandler.bind(this);
    }
    navHandler(e) {
        e.preventDefault();
        console.log('clicked intro');
    }
    render() {
        return (
            <nav id="nav">
                <div id="nav_wrapper">
                    <Author />
                    <NavTab
                        onClick={this.navHandler}
                        icon="Icon"
                        label="Intro"
                    />
                    <NavTab icon="Icon" label="About Me" />
                    <NavTab icon="Icon" label="Portfolio" />
                    <NavTab icon="Icon" label="Get In Touch" />
                    <Footer />
                </div>
            </nav>
        );
    }
}

Try this so you can get something printing to the console:

class NavPanel extends Component {
  constructor(props) {
    super(props);
    this.navHandler = this.navHandler.bind(this);
  }
  // Adjust the nav handler to take an argument
  // in addition to the event it always gets passed
  navHandler(e, someArg) {
    e.preventDefault();
    console.log(`nav handler triggered with ${someArg}`);
  }

  render() {
    return (
      <nav id="nav">
        <div id="nav_wrapper">
          <Author />
            <NavTab onClick={e => this.navHandler(e, "I'm the intro tab")} icon="Icon" label="Intro" />
            <NavTab onClick={e => this.navHandler(e, "I'm the about tab")} icon="Icon" label="About Me" />
            <NavTab onClick={e => this.navHandler(e, "I'm the portfolio tab")} icon="Icon" label="Portfolio" />
            <NavTab onClick={e => this.navHandler(e, "I'm the contact tab")} icon="Icon" label="Get In Touch" />
            <Footer />
        </div>
      </nav>
    );
  }
}

Event listener callbacks take a single argument (the event object), so to get around that, you use a closure - the anonymous function takes the single [event object] argument, which then executes the handler, which takes that event object + anything else you want. Note this isn’t React-specific, this is just exactly the same as in [browser-specific] JS

1 Like

Problem
So my click event runs in the browser without me clicking on it. Why is it doing this and how do I stop it.
onClick={console.log('intro')}

See full code on Github

class Nav extends Component {
    constructor(props) {
        super(props);
        this.pageHandler = this.pageHandler.bind(this);
    }
    pageHandler() {
        switch (expr) {
            case 'intro':
                break;
            case 'about':
                break;
        }
    }
    render() {
        return (
            <nav id="nav">
                <div id="nav_wrapper">
                    <Author />
                    <Tab
                        onClick={console.log('intro')}
                        icon="Icon"
                        label="Intro"
                    />
                    <Tab
                        // onClick={this.pageHandler}
                        icon="Icon"
                        label="About Me"
                    />
                    <Tab icon="Icon" label="Portfolio" />
                    <Tab icon="Icon" label="Get In Touch" />
                    <Footer />
                </div>
            </nav>
        );
    }
}

wait for the click before you console.log()

<Tab onClick={() => console.log('intro')} icon="Icon" label="Intro" />;

Look at the click even for the div below that. How would i run pageHandler with different parameters for each div. if insay pageHandler(‘intro’) it just runs automatically. How do i avoid that without having to make a function for each div.

I’m not sure I can explain it better than @DanCouper did above, when a click event happens it hits the callback back function with an event parameter, you then read from that callback the parameter and attach any more variables you have and call your final function that does your page handling.

Oh ok sry. Didnt read his reply well enough. Thx

hey me again.

so i changed some things ie. onClick={() => console.log('intro')} but its not registering my clicks. nothing happens.

Github

hmmmm… strange indeed, could you wrap your code in codepen and include a link, easier to troubleshoot…

figured it out.
so apparently you cant put onClick directly onto <Tab />.
I tried adding it to a div inside Tab instead and it works, so i’m just gonna use props.expr to assign the params for each event.

Ah sorry about that, I missed that, you normally to pass the handler via props (sorry if my reply was a bit garbled as well). That’s a key reason why you bind the method in the constructor: it means you can safely pass that function to another object but keep the this value of Nav.

Note this is still the same as all JS functions, ie if you try to use onClick (ie basically addEventListener) on something that isn’t the actual element, what is e going to be?

How do I change the state of one component with an event from another component.

This is what ive been ultimately trying to do for almost 2 days now. I want to click a button on <Nav> to render something in <Pages/>. I’m not making any head way.

I can’t change the state of a class from another class, but that was my initial approach.

Is there a method for doing something like this?