8

so now that we cant use the hooks as old style of event functions beside disabling the warning what is the best way to call event function that does not violate the rule

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}> // Lambdas are forbidden in JSX attributes due to their rendering performance impact (jsx-no-lambda)
        Click me
      </button>
    </div>
  );
}
Amir-Mousavi
  • 4,273
  • 12
  • 70
  • 123
  • 1
    `const inc = () => setCount(prevCount => prevCount + 1);` and then ` – Amir-Mousavi Mar 04 '19 at 13:22
  • which just suppresses the warning but improves nothing. – Monsignor May 05 '20 at 10:49
  • @Monsignor well actually this question is not useful anymore as tslint is deprecated and the official CRA eslint with typescript plugin does not have this rule by default. And also yes just disabling this warning is the best solution unless lambdas really are affection the performance of you app or the component – Amir-Mousavi May 05 '20 at 21:58

1 Answers1

19

With hooks the performance penalty to creating inline arrow function is negligible to the benefits that it has over class components and hence you need not worry arrow functions in render.

You can disable this eslint rule.

However you still improve your code by writing a increment method and memoizing it using useCallback hook. This is particularly useful whenn you are trying to pass down the handler to nested components which you can then optimize for re-render by using React.memo

const Button = React.memo(function Btn({increment}) {
    return (
       <button onClick={increment}>
          Click me
      </button>
    )
})
function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = React.useState(0);
  const increment = React.useCallback(() => {
      setCount(prev => prev+1);
  }, [])
  return (
    <div>
      <p>You clicked {count} times</p>
      <Button increment={increment}/>
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app"/>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • it seems that this usage of callBack is wrong `useCallback(fn, inputs) is equivalent to useMemo(() => fn, inputs).` but we dont have inputs here – Amir-Mousavi Mar 04 '19 at 13:15
  • @Amir-Mousavi, inputs are needed to tell useCallback that on these inputs change, it creates a new function, but if you don't provide inputs, it will never update the function once created and there is no need to do that too since setCount uses function callback pattern – Shubham Khatri Mar 04 '19 at 13:16
  • yes, and this was my point, so the snippet you have provided here has compile error – Amir-Mousavi Mar 04 '19 at 13:18
  • in `tsx`, we have to provide both arguments – Amir-Mousavi Mar 04 '19 at 13:24
  • Sure, Provide `[]` then – Shubham Khatri Mar 04 '19 at 13:24
  • Are you sure `useCallback` actually improves the code here? The inline function passed as its argument is still created for every re-render, it's just that `useCallback` will keep returning the first function you render with. Generally, you'd use `useCallback` so that you pass it's returned memoized function as a prop to a memoed component (which doesn't rerender if props stay the same). That way parent state changes don't re-render the memoed component (React.memo). – justin Mar 19 '21 at 09:45
  • 1
    @justin In the above example, useCallback doesn't contribute tto anything. It will be useful when the component to whichc you are passing it as a props is not a DOM element but aa custom react component, in which case you can use React.memo or extend PureComponent for optimzation. I will update my answer to make it more clearer – Shubham Khatri Mar 19 '21 at 10:25