Javascript loop with dynamic react component handler binding

I am new to Javascript/ReactJs world. I am building a side nav. Below are some part of my code –

import React, {Component} from "react";
import Link from "./Link/Link";
    
class Sidebar extends Component {
    
    state = {
        dashboard: {
            name: "Dashboard",
            href: "#",
            active: true,
            svgPath: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6",
            children: []
        },
        team: {
            name: "Team",
            href: "#",
            active: false,
            svgPath: "M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z",
            children: [
                {
                    name: "Overflow",
                    href: "#",
                },
                {
                    name: "Members",
                    href: "#",
                },
                {
                    name: "Calender",
                    href: "#",
                },
                {
                    name: "Settings",
                    href: "#",
                }
            ]
        }
    } 

    navClickHandler = (e, key) => {
        console.log(e, key)
    }
    
    render() {
        let navLinks = [];
        for (const item in this.state) {
            navLinks.push(<Link key={item} navClicked={(e, item) => this.navClickHandler(e, item)} config={this.state[item]} />)
        }
    
        return (
            <div className="hidden bg-indigo-700 md:flex md:flex-shrink-0">
                <div className="flex flex-col w-64 border-r border-gray-200 pt-5 pb-4 bg-white overflow-y-auto">
                    <div className="flex items-center flex-shrink-0 px-4">
                        <img className="h-8 w-auto"
                                 src="https://tailwindui.com/img/logos/workflow-logo-indigo-600-mark-gray-800-text.svg"
                             alt="Workflow" />
                    </div>
                    <div className="mt-5 flex-grow flex flex-col">
                        <nav className="flex-1 px-2 space-y-1 bg-white" aria-label="Sidebar">
                            {navLinks}
                        </nav>
                    </div>
                </div>
            </div>
        );
    }
}
export default Sidebar;

How can I get the item value inside the navClickedHandler function –

let navLinks = [];
for (const item in this.state) {
    navLinks.push(<Link key={item} navClicked={(e, item) => this.navClickHandler(e, item)} config={this.state[item]} />)
}

Actually, I want to use that key(item) to check which of the side-nav is active. It will change the state object based on the click.

console.log in nacClickHandler is giving undefined.

Answer

You are not passing item to Link, so you cannot get it as an argument back from the click event.

So change this:

navClicked={(e, item) => this.navClickHandler(e, item)} 

to this:

navClicked={e => this.navClickHandler(e, item)} 

Or, you can change your <Link/> component to something like this:

const Link = ({navClicked, item}) => (
  <div onClick={e => navClicked(e, item)}></div>
);

And pass item as a prop:

<Link key={item} item={item} navClicked={this.navClickHandler} config={this.state[item]} />

The second option is preferable since it allows you to pass the same function reference always, thus avoiding redundant renders (provided that Link is a PureComponent, or a functional component wrapped in memo)

Leave a Reply

Your email address will not be published. Required fields are marked *