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