Come and join us!

“The Newbies of Little Wo Shan” provides front-end developers with technical information and a series of basic articles. For a better user experience, please go to xhs-rookies.com/ to learn the latest articles.

“Code Tailor “, if you are interested in our article, or would like to make some suggestions, please follow the official account of “Rookie of Xiaohe Mountain” on wechat and contact us. You can also view our article on wechat. Every suggestion or approval is a great encouragement to us!

preface

In this article, our main purpose is to understand the use of useCallback.

useCallback

define

UseCallback returns a Memoized callback function.

const memoizedCallback = useCallback(fn, deps)
Copy the code

Parameter required for useCallback

  • fn: a function will eventually return the callback function, which can only be called indepsUpdates only when parameters change.
  • deps: Used to triggerfnThe list of arguments that the callback function changes.

Note: deps is an array, which means there can be many changes to fn’s parameters.

Passing the inline callback function and the array of dependencies as arguments to useCallback returns the Memoized version of the callback function, which is updated only when a dependency changes. This is useful when you pass callback data to child components that are optimized and use reference equality to avoid unnecessary rendering (such as shouldComponentUpdate).

How to use

Let’s start with a simple example.

This is a child component that takes an FN method of the parent class and displays its button.

const ChildComponent = memo(function (props) {
  console.log('child render! ')
  return <Button onClick={props.fn}> showTime</Button>
})
Copy the code

Reactjs.org (reactjs.org) reactjs.org (reactjs.org)

This is a parent component that has a counter, a number increment button, and this child component.

function Main() {
  const [count, setcount] = useState(0)

  const ShowTime = () = > {
    console.log('now time :' + new Date()}return (
    <Row
      style={{
        'flex-direction': 'column'}} >
      <Col>
        <Title>Index: {count}</Title>
      </Col>
      <Col>
        <Button onClick={()= > setcount(count + 1)}>increase</Button>
      </Col>
      <Col>
        <ChildComponent fn={ShowTime} />
      </Col>
    </Row>)}Copy the code

We can see that the count increases when we click the increase button, which is normal and reasonable.

But if we open up our browser console at this point, we’ll see that the child ChildComponent keeps rendering.

For us, the child component should only be affected by the childname argument. If fn is not changed, we should not render.

Note: The reason why the subcomponent keeps rendering is because the ShowTime method is constantly recreating, which then causes the props to be different for the subcomponent, thus rendering the subcomponent

This is where we use the useCallback.

function Main() {
  const [count, setcount] = useState(0)

  const useMemoryCallback = useCallback(() = > {
    console.log('now time :' + new Date()}, [])return (
    <Row
      style={{
        'flex-direction': 'column',
        marginLeft: '10px'}} >
      <Col>
        <Title>Index: {count}</Title>
      </Col>
      <Col>
        <Button onClick={()= > setcount(count + 1)}>increase</Button>
      </Col>
      <Col>
        <ChildComponent fn={useMemoryCallback} />
      </Col>
    </Row>)}Copy the code

At this point, we return this function in the useCallback, since the deps parameter is empty, there is no need to change it, so when we click the increase button we will not trigger the render of the child component.

How to check

Dependency arrays (DEPS) are not passed as arguments to callback functions. Conceptually, though, it looks like this: all values referenced in callback functions should appear in dependency arrays. In the future, compilers will get smarter and it will be possible to create arrays automatically.

We recommend enabling the Strict-deps rule in eslint-plugin-react-hooks. This rule warns when you add false dependencies and suggests how to fix them.

summary

  • useCallbackWhich brings us to memory functions, combining subcomponents anduseMemoIt can optimize component loading.
  • If the child component accepts a method as a property, we are using itReact.memoThis is needed to avoid unnecessary rendering by child componentsuseCallbackCooperate, or elseReact.memoWould be meaningless.

Next day forecast

In the next section, we will introduce hook rules, so stay tuned!