loading...
Cover image for understanding React Hooks and Effects

understanding React Hooks and Effects

danl profile image Dan L. ・2 min read
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

React Effects are normally triggered by React after each RENDER of the component.

An effect can contain also a cleanup method by returning it from the callback function like this

useEffect(() => {
  AppAPI.subscribeToNameChange(nameChanged);

  document.title = "name is ${name}"

  return () => {
    AppAPI.unsubscribeToNameChange(nameChanged);
  }
});

Multiple hooks can be used to separate concerns:

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  // ...
}

useEffect lifecycle

An important thing to note is the effect callbacks are applied at both lifecycles of init/destroy and after each render.
It is helpful because each state change should produce a consistent refresh of the component's UI.
This feature is provided out of the box, while for class based React components this needs to be addressed manually via componentDidUpdate.
Also any listeners bound during the effect's execution are likely to be linked to the current state of the component. So if the state changes, these listeners should be rebound:

function FriendStatus(props) {
  // ...
  useEffect(() => {
    // ...
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

However this is prone to performance issues if the callback execution is expensive.
To help with that, React provides a dirty check feature, by providing an extra param to useEffect:

useEffect(() => {
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  return () => {
    ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  };
}, [props.friend.id]); // Only re-subscribe if props.friend.id changes

Source: https://reactjs.org/docs/hooks-effect.html

Posted on by:

Discussion

pic
Editor guide