Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use useCallback in React #966

Open
onmyway133 opened this issue Jan 26, 2024 · 0 comments
Open

How to use useCallback in React #966

onmyway133 opened this issue Jan 26, 2024 · 0 comments

Comments

@onmyway133
Copy link
Owner

The use of useCallback and useMemo in React hooks is an adaptation to address certain limitations inherent in the functional programming style adopted by React. In JavaScript, every entity, whether it's a function, variable, or any other type, gets created in memory when the code within a function's scope is executed. This poses a challenge for React's rendering logic, which determines the need for re-rendering based on changes in input props and context. Consider an example without useCallback:

const Component = () => {
  const [counter, setCounter] = useState(0);

  const incrementCounter = () => {
    setCounter(counter + 1);
  }

  return <div>
    Count: {counter}<br/>
    <button onClick={incrementCounter}>Increase</button>
  </div>
}

In this scenario, a new instance of incrementCounter is created every time the component renders, leading React to perceive each instance as distinct. useCallback, however, caches the initial version of a function and reuses it, provided its dependencies haven't changed.

const Component = () => {
  const [counter, setCounter] = useState(0);

  const incrementCounter = useCallback(() => {
    setCounter(counter + 1);
  }, [])

  return <div>
    Count: {counter}<br/>
    <button onClick={incrementCounter}>Increase</button>
  </div>
}

With the above code, React recognizes incrementCounter as the same function across re-renders. However, useCallback introduces a new issue: the cached function might not reflect the latest variable values. It sees the variables as they were during its initial creation. To address this, dependencies are declared in useCallback, signaling when to update the cached function. In our example, we update incrementCounter when counter changes:

const Component = () => {
  const [counter, setCounter] = useState(0);

  const incrementCounter = useCallback(() => {
    setCounter(counter + 1);
  }, [counter])

  return <div>
    Count: {counter}<br/>
    <button onClick={incrementCounter}>Increase</button>
  </div>
}

This approach ensures that the component does not re-render unnecessarily. useState, useCallback, and useMemo serve to replicate traditional class-based functionality, bringing functional programming closer to a procedural style.

useMemo functions similarly to useCallback but for variables and objects. It helps reduce unnecessary re-renders by returning cached values unless specified dependencies change.

Conclusion

Despite these benefits, the new hooks-based approach in React, especially the use of useCallback, can be somewhat counterintuitive and prone to errors, such as creating unintentional loops. This complexity was not present in the class-based React paradigm.

Originally, the class-based approach in React was more straightforward in some respects. While useCallback minimizes unnecessary re-renders, it also requires re-creating the function when dependencies change, potentially leading to more re-renders than in the class-based model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant