shanik1986
shanik1986

Reputation: 63

Can't pass a parameter through onClick

I'm trying to create a Counter component that has two buttons and a counter. One button increases the counter and the other decreases it. I don't want to create two separate onClick handlers so I'm trying to pass a parameter through the onClick. The thing is I can't access it afterwards in the handler function since it's undefined.

Counter Component

import Button from './Button.jsx';

function Counter() {
    const [count, setCount] = useState(0);
    const increaseLabel = 'Increase';
    const decreseLabel = 'Decrese';

    function clickHandler(e) {
        const currentLabel = e.target.label;
        console.log(e.target) // <button label="Increase">Increase</button>
        console.log(e.target.label) // undefined

        if (currentLabel === increaseLabel) {
            setCount(count + 1)
        } else {
            setCount(count - 1)
        }
    }

    return (
        <div>
            <Button label={increaseLabel} onClick={clickHandler} />
            <Button label={decreseLabel} onClick={clickHandler} />
            <br/>
            <h2>{count}</h2>
        </div>
    )
}

Button Component

import React from 'react';

function Button(props) {
    const label = props.label;
    return (
        <button label={label} onClick={props.onClick}>{label}</button>
    ) 
}

export default Button;

Any idea on how I can access the parameter from within the handler?

Upvotes: 1

Views: 63

Answers (2)

jlents
jlents

Reputation: 820

Instead of pointing onClick to clickHandler directly, you can wrap it in an anonymous function, which will allow you to supply a second argument to your clickHandler function:

    return (
        <div>
            <Button label={increaseLabel} onClick={(e) => clickHandler(e, "foo")} />
            <Button label={decreaseLabel} onClick={(e) => clickHandler(e, "bar")} />
            <br/>
            <h2>{count}</h2>
        </div>
    )

Upvotes: 1

devserkan
devserkan

Reputation: 17638

I agree with @dave, depending on the label as an attribute is not so nice but since you are passing it as a prop you don't need to struggle with event but instead, you can use this prop in your click handler of your button and pass it back to clickHandler function.

function Counter() {
  const [count, setCount] = React.useState(0);
  const increase = "Increase";
  const decrease = "Decrese";

  function clickHandler(type) {
    return type === increase
      ? setCount((prev) => prev + 1)
      : setCount((prev) => prev - 1);
  }

  return (
    <div>
      <Button label={increase} onClick={clickHandler} />
      <Button label={decrease} onClick={clickHandler} />
      <br />
      <h2>{count}</h2>
    </div>
  );
}

function Button({ label, onClick }) {
  return <button onClick={() => onClick(label)}>{label}</button>;
}

ReactDOM.render(
  <Counter />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root" />

Upvotes: 0

Related Questions