0

Problem

I'm trying to understand why my event handler below navItemClick isn't firing to the console when an item in the list is clicked. Also, I'm trying to figure out if it's possible to add the onClick event to the NavigationSidebarItem function to reduce repeating it on each item on the return in the NavigationSidebar component.

The component renders correctly; no errors. I also am able to see the console lines for the constructor as well as the JSX loading successfully. Just no clicky clicky message!

Code Example

class NavigationSidebar extends React.Component {
    constructor(props) {
        super(props);
        this.navItemClick = this.navItemClick.bind(this);
        console.log('NavigationSidebar:constructor => success');
    }

    navItemClick(event)
    {
        console.log('this.navItemClick: clicked');
    }

    render()
    {
        return (
                <ul>
                    <NavigationSidebarItem description="Item1" onClick={this.navItemClick} />
                    <NavigationSidebarItem description="Item2" onClick={this.navItemClick} />
                    <NavigationSidebarItem description="Item3" onClick={this.navItemClick} />
                </ul>
        )
    }
};

function NavigationSidebarItem(props) {
    return (
        <li>
            <span>{props.description}</span>
        </li>
    );
}

ReactDOM.render(
    <NavigationSidebar/>,
    document.getElementById('navigation-sidebar')
);

console.log('NavigationSidebar.jsx:loaded => finished');
1
  • @AndrewL: That results in a ReferenceError: navItemClick is not defined at NavigationSidebar.render. I'm fairly certain the "this" is required to define the scope. Good try though... I haven't felt this stuck in a long time! Especially over something fairly simple... it seems like an elementary React.js example. Commented Jun 11, 2018 at 21:35

2 Answers 2

3

You are possibly confusing the usage/relationship between REACT components and DOM elements written in JSX (within components).

When you bind your onClick to <NavigationSidebarItem /> what you are actually doing is passing a prop to the functional component <NavigationSidebarItem />, called props.onClick. This is not the same as attaching an onclick event to a DOM element.

You should pass the onClick handler to the component, at which point you will have made props.<yourOnClickEventHandle> available to <NavigationSidebarItem />.

You then need create your onClick on the desired DOM element within the render function, which will bind it to the DOM element.

To avoid confusion when returning to the code you should not use the property name onClick as it may confuse you later. Say what you mean/intend the method to do and label all event handlers with a familiar structure. e.g. showMeKittensHandle (Handle being the operative word, not kittens).

class NavigationSidebar extends React.Component {
    constructor(props) {
        super(props);
        this.navItemClickHandle = this.navItemClick.bind(this);
        console.log('NavigationSidebar:constructor => success');
    }

    navItemClickHandle(event)
    {
        console.log('this.navItemClick: clicked');
    }

    render()
    {
    console.log(this.navItemClick)
        return (
                <ul>
                    <NavigationSidebarItem description="Item1" navItemClickHandle={this.navItemClickHandle} />
                    <NavigationSidebarItem description="Item2" navItemClickHandle={this.navItemClickHandle} />
                    <NavigationSidebarItem description="Item3" navItemClickHandle={this.navItemClickHandle} />
                </ul>
        )
    }
};

function NavigationSidebarItem(props) {
    return (
        <li onClick={props.navItemClickHandle}>
            <span>{props.description}</span>
        </li>
    );
}

ReactDOM.render(
    <NavigationSidebar/>,
    document.getElementById('navigation-sidebar')
);

console.log('NavigationSidebar.jsx:loaded => finished');

Example: https://jsfiddle.net/69z2wepo/189598/

Sign up to request clarification or add additional context in comments.

8 Comments

I made these changes; still no console data coming from the navItemClick function. Regarding code cleanliness though, is there no way to eliminate the need for the navClickItem=this.navItemClick? Also, in your example above, props.navClickItem should be navItemClick. Should it not?
Also, I've tried is moving the event handling to the sub-component level (e.g. to NavigationSidebarItem instead of NavigationSidebar); however, my understanding with React.js scope is that I will run into troubles determining state for the selected navigation item if I put the code down there. Also, when I tried that, still no event firing even when I tried this method. I should also mention that events do fire correctly in Javascript and that I'm virtually plug-in free. This example is being rendered client-side using Browser.min.js (no server side stuff just yet).
Hmm. I am testing this in jscomplete.com/repl and it is working. With regards to the name, 'No', once you pass a property to a REACT component via myPropName="{this.someProp}". It will become available on props in the component. i.e. props.myPropName
In terms of state in the functional component, that is not it's concern. Class based components manage state functional components only work from the properties they are provided during the cascade of state. That is my understanding.
I have added a JS fiddle to the solution and switched your console.log to alert for ease. You should see it working now.
|
0

You can bind a click like this:

const yourFunction = (arg) => console.log(arg);

<C onClick={(event) => yourFunction('Hello')} />

will log Hello when you click;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.