ReactJS – How to improve performance (1)

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

Be the first to comment

Leave a Reply

Your email address will not be published.


*