0

Im trying to pass in a method and its needed parameters with "onClick" but it wont work.

I read you can do it like this : onClick={() => handleSort(column)} but also that the problem with using an arrow function in the render call is it will create a new function every time, which ends up causing unneeded re-renders.

function ToggleSwitch() {
  const [values, setValues] = React.useState({
    astma: "off",
    
  });

  function toggle (nameIn, valueIn){
      console.log("Toggle")
    const {name, value} = (nameIn, valueIn);
    if (value === "off") {
      setValues({
        ...values,
        [name]: "on",
      });
    } else if (value === "on") {
      setValues({
        ...values,
        [name]: "off",
      });
    }
  };
  
  //return just the function and make the html in the page and on klick use the toggle function
  //remember to export values as well.
  return (
    <div
      className={`switch ${values.astma}`}
      onClick={toggle("astma", values.astma)}
      id={"astma"}
      name={"astma"}
    />
  );
}

ReactDOM.render(<ToggleSwitch />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
Janez Kuhar
  • 3,705
  • 4
  • 22
  • 45
Mr.Gomer
  • 501
  • 5
  • 14
  • can you post a codesandbox? what are nameIn and valueIn? – Apostolos May 28 '21 at 17:58
  • I edited it now. Look at onclick it should be more clear. – Mr.Gomer May 28 '21 at 18:02
  • first thing: `onClick={() => toggle("astma", values.astma)}`. then, if you do that, what is the problem? – Apostolos May 28 '21 at 18:03
  • the problem with using an arrow function in the render call is it will create a new function every time, which ends up causing unneeded re-renders. – Mr.Gomer May 28 '21 at 18:04
  • Where did you red this? – ulou May 28 '21 at 18:18
  • https://stackoverflow.com/questions/29810914/react-js-onclick-cant-pass-value-to-method – Mr.Gomer May 28 '21 at 18:18
  • So, you got exact answer for you question. Why did you create new one? – ulou May 28 '21 at 18:20
  • Thats a answer from 2017... thats 4 years ago surely something must have changed. – Mr.Gomer May 28 '21 at 18:22
  • Also im using Hooks – Mr.Gomer May 28 '21 at 18:25
  • Interesting thing is that you know that something is definitely changed, but you created question on facts from SO answer that is 6yo, that says: `to not use arrow function in onClick`, while React is 8yo :D – ulou May 28 '21 at 18:30
  • I have no idea what you just said. I googled my issue and found a old answer which said dont use it and then gave another answer that did not use hooks so i made my own question and specifically put react-hooks in the description and in the tags. – Mr.Gomer May 28 '21 at 18:34
  • Yes this is what I'm talking about. React is 8 years old, while answer that you found has been written 6 years ago. Anyway, let's do not off-top here. I think you already got your answer. – ulou May 28 '21 at 18:40
  • Act they also discuss some thing about currying and why you need to use catch when u use it but its way to complicated and goes above my head. – Mr.Gomer May 28 '21 at 18:43
  • you can pass an arrow function. it won't trigger rerenders, only a new function created and passed down to onClick on each rerender. Could be an issue if you were passing as props to a memoized component though. – buzatto May 28 '21 at 18:53

1 Answers1

1

If you don't want to use arrow for some reason. You can use currying way instead:

function ToggleSwitch() {
  const [values, setValues] = React.useState({
    astma: "off",
    
  });

  const toggle = (nameIn, valueIn) => e => {
    console.log("Toggle", nameIn, valueIn)
    const {name, value} = (nameIn, valueIn);
    if (value === "off") {
      setValues({
        ...values,
        [name]: "on",
      });
    } else if (value === "on") {
      setValues({
        ...values,
        [name]: "off",
      });
    }
  }
  
  //return just the function and make the html in the page and on klick use the toggle function
  //remember to export values as well.
  return (
    <div
      className={`switch ${values.astma}`}
      onClick={toggle("astma", values.astma)}
      id={"astma"}
      name={"astma"}
    >Currying is cool. Click ME!</div>
  );
}

ReactDOM.render(<ToggleSwitch />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
ulou
  • 5,542
  • 5
  • 37
  • 47
  • This currying solution looks like black magic to a React beginner like myself! :) – Janez Kuhar May 28 '21 at 18:35
  • @JanezKuhar Currying is general `functional programming` thing, it's not react or js thing itself :). Its basically function that returns function so you can call it like this: `toggle(event)(nameIn, valueIn)` – ulou May 28 '21 at 18:37
  • I like currying myself but for this question, this solution still will create a new function for every rerender, which that's the question goal. – buzatto May 28 '21 at 18:50