0

I am building a website that allows a user to create a job opening, assign to it different requirements and delete it.

I have two main components:

  • HRdashboard is the parent component in which all the job openings are listed.

  • MyOpeningCard is the card that contains information of a single job opening. It comes from the .map function in the parent component:

HRdashboard

function HRdashboard({changeAuthLoginHR}) {
const [HRuser, setHRuser] = React.useState([]);
const [openings, setOpenings] = React.useState([]);

useEffect( ()=> {

    let unmountedOpenings = false
    async function getAllOpenings(){
        let response = await  axios("http://www.localhost:3000/api/v1/openings");
        if(!unmountedOpenings)
            setOpenings(response.data)
    }

    let jwt = window.localStorage.getItem('jwt')
    let result = jwtDecode(jwt)
    setHRuser(result)
    changeAuthLoginHR()
    getAllOpenings()
    return () => {
        unmountedOpenings = true
    }
    }, [],
)


return(
    <div>
        <Container style={{marginTop: "50px"}}>
            <Row>
                    {openings.map(opening =>
                        <Col>
                            <MyOpeningCard key={opening.id} opening={opening} /> # Here is where the child is
                        </Col>
                    )}
            </Row>
        </Container>
    </div>
)

}

MyOpeningCard

function MyOpeningCard({opening}) {

    return(

        <div>
            <Card style={{ width: '18rem', marginTop: "15px"}}>
                <Card.Body>
                    <Card.Title>{opening.title}</Card.Title>
                    <Card.Subtitle className="mb-2 text-muted">Requirements: </Card.Subtitle>
                    <Card.Text>
                        {opening.requirements[0].requirements.map(requirement => <li>{requirement}</li>)}
                    </Card.Text>
                    <div>
                    <Card.Link href="#" onClick={console.log(opening.id)}>Click Here</Card.Link> # If I click here, it console.log all the IDs, not only this opening id.
                    </div>
                </Card.Body>
            </Card>
        </div>
    )

}

My question:

If I click on Click Here in my child component, it triggers console.log(opening.id). I was expecting to see in console only the opening.id of the Job Opening I click. However, I see all the ids of the openings. Why is it so?

Magofoco
  • 5,098
  • 6
  • 35
  • 77
  • 3
    Should be callback, i.e. `onClick={() => console.log(opening.id)}` – Drew Reese Dec 30 '19 at 17:59
  • Does this answer your question? [React onClick function fires on render](https://stackoverflow.com/questions/33846682/react-onclick-function-fires-on-render) – Drew Reese Dec 30 '19 at 18:01

2 Answers2

1

Because your onClick prop is calling a function which immediately runs the same time your child component is rendered, without even clicking, for all the child components.

onClick={console.log(opening.id)}

So, when you use the .map() method, all of your <MyOpeningCard /> components get rendered, each of them immediately calling console.log() again and again, hence you see all the ids logged in the console.

You should pass a callback, instead, to the onClick prop which will be executed only when a click happens.

Change it to

onClick={() => { console.log(opening.id) }}
Akshit Mehra
  • 747
  • 5
  • 17
1

Parentheses after a function name executes the function. even-though you didn't mean to do that, that's why wrapping it with an additional Arrow Function is needed, it happens as:

() => console.log('something'), this Arrow Function is not going to be invoked until the click actually occurs.

while if you pass console.log this way -no parenthesses-, it'll be logging the whole Event only upon the Click event occurrence.

Sultan H.
  • 2,908
  • 2
  • 11
  • 23