How to use useCallback?
Use useCallback to save a function unless dependencies are changed
function User({ userId }) { const [user, setUser] = useState({ name: '', email: '' }); // This function has userId as a dependency const fetchUser = async () => { const res = await fetch( `https://jsonplaceholder.typicode.com/users/${userId}` ); const newUser = await res.json(); setUser(newUser); }; useEffect(() => { fetchUser(); }, []); // eslint-plugin-react-hooks will warn that fetchUser needs to be put in as dependency here!!! return ... } export default User;
... const fetchUser = async () => { const res = await fetch( `https://jsonplaceholder.typicode.com/users/${userId}` ); const newUser = await res.json(); setUser(newUser); // 🔴 setState triggers re-render }; useEffect(() => { fetchUser(); }, [fetchUser]); // This will cause infinite loop !!! // Because fetchUser is a new function on every render // In React functions defined in function components get re-created on every render because of closure ...
// Define fetchUser with useCallback // so that the function stays the same, unless userId changes. const fetchUser = useCallback(async () => { const res = await fetch( `https://jsonplaceholder.typicode.com/users/${userId}` ); const newUser = await res.json(); setUser(newUser); }, [userId]); useEffect(() => { fetchUser(); }, [fetchUser]); // ✅ fetchUser stays the same between renders
By using useCallback, you can prevent unnecessarily re-rendering components by returning the same instance of the function that is passed instead of creating a new one each time.
What is the similar usage of useCallback in class component?
class User extends Component { constructor() { this.state = { name: '', email: '' } } // No need to worry about "userId" dependency because all the dependencies are maintained on your instance as props or state fetchUser = async() => { const res = await fetch( `https://jsonplaceholder.typicode.com/users/${this.props.userId}` ); const newUser = await res.json(); this.setState({ name: newUser.name, email: newUser.email }); }; fetchUserProp = this.fetchUser.bind(this); // This line is essentially "useCallback" for a class component!!! render() { return <SomeOtherComponent fetchMovie={this.fetchMovieProp}/> } }
What are useMemo() and React.memo()?
If the computationally expensive code accepts arguments and returns a value, you would need to use useMemo so you could keep referencing that value between renders without re-running the computationally expensive code.
In order to keep a function instance persistent for multiple renders, useCallback is needed. This is like placing a function outside the scope of your react component to keep it intact.
How to fetch multiple APIs basing on priority?
How to prefetch multiple APIs in the background?
Other improvements
- Remove console.log by babel-plugin-transform-remove-console
performance#using-consolelog-statements
Leave a Reply