最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Questions about useCallback hook and anonymous function - Stack Overflow

programmeradmin2浏览0评论

When passing a callback function, especially when passing a parameterized function, I know that I should use the useCallback hook because the use of anonymous functions can adversely affect performance.

the example of anonymous function I said is like this.

import React, { useState } from 'react';

const Component = () => {
  const [param, setParam] = useState('');
  ...

  return (
    ...
    <SomeComponent
      onClick={() => setParam('parameter')}
      {...others}
    />
  );
}

In the process of converting an anonymous function to use this hook, I encountered an error saying 'Too many renders' or it didn't work properly. But I don't know exactly in what situation and in what situation.

and I used useCallback like below.

import React, { useState, useCallback } from 'react';

const Component = () => {
  const [param, setParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );
}

However, when using an anonymous function to return within useCallback, it also worked.

This means code like here. (Only the differences pared to the code above.)

  const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);

In this situation, I wonder if it's worse than just using an anonymous function inside the useCallback if I simply use an anonymous function instead of using this hook.

When passing a callback function, especially when passing a parameterized function, I know that I should use the useCallback hook because the use of anonymous functions can adversely affect performance.

the example of anonymous function I said is like this.

import React, { useState } from 'react';

const Component = () => {
  const [param, setParam] = useState('');
  ...

  return (
    ...
    <SomeComponent
      onClick={() => setParam('parameter')}
      {...others}
    />
  );
}

In the process of converting an anonymous function to use this hook, I encountered an error saying 'Too many renders' or it didn't work properly. But I don't know exactly in what situation and in what situation.

and I used useCallback like below.

import React, { useState, useCallback } from 'react';

const Component = () => {
  const [param, setParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );
}

However, when using an anonymous function to return within useCallback, it also worked.

This means code like here. (Only the differences pared to the code above.)

  const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);

In this situation, I wonder if it's worse than just using an anonymous function inside the useCallback if I simply use an anonymous function instead of using this hook.

Share Improve this question asked Jan 24, 2020 at 10:33 Anthony MinAnthony Min 231 silver badge5 bronze badges 4
  • If your function is as small as that, I doubt you'll gain any performance by even using useCallback.. But you loose a lot of readability instead, when -> onClick={(params) => setParam(params)} would do the same. – Keith Commented Jan 24, 2020 at 10:40
  • @Keith thanks for the ment. But that code is just an example. Maybe it was an inappropriate example. And the point of my question was, "Is the same performance penalty when returning anonymous functions within` useCallback` just using anonymous functions? " In other words, people remend using useCallback because anonymous functions have a negative impact on performance, and I wonder if I can use them if they work correctly when I return an anonymous function inside` useCallback`. – Anthony Min Commented Jan 24, 2020 at 10:58
  • use useCallback when you need to optimize child re-renders by passing the same reference of the function and the child ponent is PureComponent/wrapped with React.memo, although it remembers the previous function reference a new function is getting created on every re-render but gets garbage collected. – Asaf Aviv Commented Jan 24, 2020 at 11:42
  • Okay. Thanks for the ment. It helped a lot! – Anthony Min Commented Jan 24, 2020 at 12:38
Add a ment  | 

3 Answers 3

Reset to default 5
  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
  );

in the above code during first render, at this statement "onClick={handleClick('parameter')}" handleClick function is called with a string named "parameter". since handleClick has setParam("parameter"), it will update state. updating state will cause re-render which will again e to same statement "onClick={handleClick('parameter')}" causing infinte loop.

following code you added later works because you are not updating state, instead returning a function, which acts as onclick handler.

const handleClick = useCallback((params) => {
    return () => setParam(params);
  },[]);

better way of doing this shoud be as follwing,

import React, { useState, useCallback } from 'react';

const Component = () => {
  const [param, setParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick}
      {...others}
    />
  );
}

ing back to your question , paring performance depends on the other function definitions and render times of child poents inside return function inside your Compoenent. let's say you have another onclickHanldier named 'anotherHandleClick' inside your app. then your ponent looks like this

const Component = () => {
  const [param, setParam] = useState('');
  const [anotherParam, setAnotherParam] = useState('');

  const handleClick = (params) => {
    setParam(params);
  };
const anotherHandleClick =(params) => {
    setAnotherParam(params);
  };
  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
<SomeComponent
      onClick={antherHandleClick('parameter')}
      {...others}
    />
  );
}

in the above ponent when any one of "SomeCompoenent" clicked entiere "Component" re-renders, so the handler functions are newly defined.and when both 's does referential equality check on onclick handler functions, they believe it is new handler function which casues them to render both. in that case it is better to use useCallBack hook as following,

const Component = () => {
  const [param, setParam] = useState('');
      const [anotherParam, setAnotherParam] = useState('');

  const handleClick = useCallback((params) => {
    setParam(params);
  },[]);
const anotherHandleClick = useCallback((params) => {
    setAnotherParam(params);
  },[]);
  ...
  return (
    ...
    <SomeComponent
      onClick={handleClick('parameter')}
      {...others}
    />
<SomeComponent
      onClick={antherHandleClick('parameter')}
      {...others}
    />
  );
}

in the above code when any one is clicked , state changes. then when rendering, useCallback make sure that onclick handler refernces didn't change. so having dependency of onclick handlers won't be rerendered.

so final thought is It's creating a function on each render in both cases. the second (because it'e wrapped in a useCallback) will return the memoized function created on the initial render

when to use useMemo or useCallback refer this

In your code:

const handleClick = useCallback((params) => {
    setParam(params);
  },[]);

You should pass the parameters into the second argment of useCallback like so:

const handleClick = useCallback((params) => {
    setParam(params);
  },[setParam,param, SETPARAMACTUALVALUE]); 
// Change SETPARAMACTUALVALUE to whatever the variable name is for the `setParam` hook

useCallback hook usage will be better if you want to save the function until hook's dependency changed. It gives you better performance because the hook remember internal function.

发布评论

评论列表(0)

  1. 暂无评论