1

I am new to react, so please be patient if I seem to not understand some obvious concept, but I wrote a profile-log function with the profiles structured like this :

{id:1, name: John Smith, age: 27, height: 186cm, Gender: male}

I am designing a react function (for learning purposes), That sorts, adds, deletes, and modifies the profiles.

To edit the profiles I am using hooks. I then use the hook functions as props inside the components.

I call a "Header" function that uses a "PrintOut" function which displays every profile on the DOM along with a delete, edit, and Change gender button.

it also takes in 3 props, the profile state, delete function, and toggle (gender-change) function. The gender-change function is initiated on a click and for now, all it is suppose to do is just console log 'You clicked gender change function' along with the ID.

instead of doing that, the console just logs that sentence for each profile without a click. And when I do click the "change gender" button, nothing happens.

I would like to know why this is the case and what can I do to fix it?

here is the code

App.js

import "./styles.css";
import Header from "./component/Header";
import Buttons from "./component/Buttons";
import { useState } from "react";
 
export default function App() {
 const [names, assortNames] = useState([
   {
     id: 1,
     name: "John",
     age: 18,
     height: 184,
     gender: "male"
   },
   {
     id: 2,
     name: "Billy",
     age: 24,
     height: 191,
     gender: "male"
   },
   {
     id: 3,
     name: "Sara",
     age: 26,
     height: 171,
     gender: "female"
   },
   {
     id: 4,
     name: "Ryan",
     height: 186,
     age: 27,
     gender: "male"
   }
 ]);
 
 const AgeFilter = () => {
   assortNames(
     [...names].sort((a, b) => {
       return b.age - a.age;
     })
   );
 };
 
 const nameFilter = () => {
   assortNames([...names].sort((a, b) => a.name.localeCompare(b.name)));
 };
 const heightFilter = () => {
   assortNames(
     [...names].sort((a, b) => {
       return b.height - a.height;
     })
   );
 };
 
 const DeleteName = (id) => {
   assortNames(names.filter((names) => names.id !== id));
 };
 
 const GenderChange = (id) => {


 console.log('You clicked gender change function', id)
 };
 
 return (
   <div className="container">
     <Buttons
       list={names}
       Age={AgeFilter}
       Name={nameFilter}
       Height={heightFilter}
     />
     <Header namez={names} functs={DeleteName} Toggler={GenderChange} />
   </div>
 );
}

Header.js

import PrintOut from "./PrintOut";
 
const Header = ({ namez, functs, Toggler }) => {
 return (
   <>
     {namez.map((name) => (
       <PrintOut key={namez.id} name={name} onDelete={functs} onToggle ={Toggler} />
     ))}
   </>
 );
};
 
export default Header;

PrintOut.js

const PrintOut = ({ name, onDelete, onToggle }) => {
  const Deleter = (id) => {
    onDelete(name.id);
  };

  return (
    <div className={name.gender === "male" ? "male" : "female"} key={name.id}>
      <h3>{name.name}</h3>
      <div className="Age-and-Height">
        <p> {name.age}</p>

        <h4> {name.height} cm</h4>
      </div>
      <button className="btn btn-delete" onClick={() => Deleter(name.id)}>
        Delete
      </button>
      <button className="btn btn-edit">Edit</button>
      <button className="btn " onClick={onToggle(name.id)}>
        Change Gender
      </button>
    </div>
  );
};

export default PrintOut;

Buttons.js

const Buttons = ({ list, Age, Name, Height }) => {
  return (
    <>
      <div className="buttons">
        <button className="btn" onClick={Age}>
          AgeSort
        </button>
        <button className="btn" onClick ={Height}>HeightSort</button>
        <button className="btn" onClick ={Name}>NameSort</button>
        <button className="btn btn-add" >Add</button>
      </div>
    </>
  );
 };
  
 export default Buttons;
1
  • 1
    onToggle(name.id) is calling your function and putting the return of that function (undefined) as the value of your onClick prop, use onClick={() => onToggle(name.id)} Commented Aug 22, 2021 at 11:19

2 Answers 2

1

Here you are directly invoking the function at the time it gets rendered:

<button className="btn " onClick={onToggle(name.id)}>
    Change Gender
</button>

So you need to change it to a callback function:

<button className="btn " onClick={() => onToggle(id)}>
     Change Gender
</button>

Also putting id to your child component

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

4 Comments

I thought the onClick even-listener was there to prevent a direct invoke? is there a circumstance where it would make sense to have the onClick event-Listener and directly invoke it?
Every time you call a function with () will invoke itself. OnClick receives a function, while you invoke it got the result of that function.
"Also putting id to your child component", you mean the button component?
It's the PrintOut component which you put name.id there.
0

You are not passing the id the that function

Toggler={() => GenderChange(id)}

2 Comments

This just gives me "id is not defined error"
It's just an example I don't know what id you want to pass, you are the one building the function

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.