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
CodePudding user response:
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.