0

I'm trying to create a react app that displays a list of the basic projects I've done using react. What I'm trying to archive is that, upon clicking the "Click me" Button, it should replace the current component (The default component) with the corresponding react component (Project) from the data array. Code -

import React, { useState } from "react";
import Birthday from "./Birthday_src/Birthday";
import Tours from "./Tours_src/App";

const data = [
  {
    id: 1,
    btn: <Birthday />,
  },
  {
    id: 2,
    btn: <Tours />,
  },
];
export default function Container() {
  const [project, setProject] = useState(Default);

  function Default() {
    return (
      <>
        <div className="container">
          <h1>15 Basic React Projects. </h1>
          <p>that are based on react...(obviously) </p>

          <div className="row row-cols-3 mt-10 mx-3 ">

            {data.map((cProject, index) => {
              const { id, btnP } = cProject;
            

              return (
                <div className="items" key={id}>

                  <p>Here goes the first project. </p>
                  <button
                    className="btn-primary btn"
                    id={`btn${id}`}
                    onClick={(e,btnP) => {
                      console.log(e.target.id);
                      console.log(btnP)
                      setProject(btnP);
                    }}
                  >
                    Click me
                  </button>
                </div>
              );
            })}
          </div>
        </div>
      </>
    );
  }

  return <>{project}</>;
}

But upon clicking the button, the "e.target.id" works perfectly fine (The console.log loggs the respective id's) but the "btnP" shows up undefined. I just need to send the current "btnP" to the useState somehow, so that the return in the functional component returns the "project" (The JSX react element, that the user wants to be displayed, depending upon the button that they have clicked.)

Thanks ~iter8

Ankit Sharma
  • 164
  • 8

1 Answers1

1

The problem is that the browser calls all these event handlers with only one argument - the event object - so if you use an event handler that accepts more than one argument, all except the first will not be passed in when the function is called (by the browser itself), therefore they will get the value undefined.

The solution here is very simple, since the btnP you want to access is already available in an outer scope (the function you are using to map over data - you're still inside it at this point). So if you simply change the function signature from

(e,btnP) => {...}

to

(e) => {...}

this should work exactly as you intend.

Robin Zigmond
  • 17,805
  • 2
  • 23
  • 34
  • Hi, Initially I thought of the exact same thing and I've already tried removing the second argument (btnP) but it showed undefined. I don't really need the e (event) argument I just passed it so that React won't mistake btnP as an Event object. Thank you for the answer, but it, unfortunately, doesn't resolve the issue. – Ankit Sharma Jun 21 '22 at 20:14
  • 1
    hi, thanks for coming back to me. I looked at your code again and realise that your property is called simply `btn` rather than `btnP`. So you also need to change your destructuring to `const { id, btn } = cProject` and similarly replace `btnP` with `btn` everywhere inside the `map` function (including in the event handler). – Robin Zigmond Jun 21 '22 at 20:16
  • I just tried that out and it worked! Thank you so much, I've literally spent hours searching for it. I somehow believed that we can assign any variable to the remaining item in the object, as I've already used Id with the Id. Thank you for correcting me, I appreciate your help :) – Ankit Sharma Jun 21 '22 at 20:19