React Hooks and jsx-no-lambda warning
Asked Answered
A

1

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>
  );
}
Anywise answered 4/3, 2019 at 12:45 Comment(3)
const inc = () => setCount(prevCount => prevCount + 1); and then <Button onClick={inc}>Anywise
which just suppresses the warning but improves nothing.Humanize
@Humanize 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 componentAnywise
T
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"/>
Tripletail answered 4/3, 2019 at 12:53 Comment(7)
it seems that this usage of callBack is wrong useCallback(fn, inputs) is equivalent to useMemo(() => fn, inputs). but we dont have inputs hereAnywise
@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 patternTripletail
yes, and this was my point, so the snippet you have provided here has compile errorAnywise
in tsx, we have to provide both argumentsAnywise
Sure, Provide [] thenTripletail
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).Apogamy
@Apogamy 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 clearerTripletail

© 2022 - 2024 — McMap. All rights reserved.