I wrote last time about the useState hook for creating stateful, functional components in React. I won't say useEffect is the second most common hook necessarily, but I think you're likely to learn it right after the useState hook because it answers a very important question about functional components: how do you handle side effects that you would normally do in componentDidMount or componentDidUnmount (among others) if you were using class components?

Before we dive into use cases and how it works, let's look briefly at the syntax. The useEffect hook takes two arguments: an effect function and a list of dependencies. Think of the effect function as an "onMount" event. This function can also return a function that you can think of as an "onUnmount" event. The list of dependencies tells useEffect when to rerun the effect function. An empty list means there are no dependencies, and the function will run once after the component is mounted. If you omit this argument altogether, the effect function will run on every re-render, which is probably not what you want. But if your function uses a value from state and needs to run again or do something different whenever that state value changes, then you can include it in the list of dependencies and React will recall your function when it changes. Here's what a simple example might look like:

import React, { useState, useEffect } from 'react';

const Form = () => {  
  const [title, setTitle] = useState('No title');
  useEffect(() => {
    document.title = title;
    return () => document.title = 'No title';
  }, [title]);

  return (
    <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
  );
};

export default Form;  

This component will update the page title to match what's typed in the input field. Note how we pass [title] as the dependencies to the effect function so that React will rerun the function when title changes (when setTitle is called).

So when would you use this hook? As you can see from the first example, interacting with the document and dom (in a non-React context) is one common use case. For instance, you might initialize a popover using a jquery plugin (if for some reason you're not happy with the existing React ones).

useEffect(() => {  
  $('#my-popover').popover();
  return () => $('#my-popover').popover('dispose');
}, []);

return <div id="my-popover" popover="Content to show" />;  

Note in this example how the dependency list is empty. That's because we don't want to rerun this function, as that would create additional popovers. We want to run it only once when the component is first created. It's also worth pointing out in this example that the useEffect function is called after rendering and mounting so the '#my-popover' selector will find a target.

Here's a couple other use cases for useEffect.

  1. Initializing an IntersectionObserver for an infinite scroll effect.
useEffect(() => {  
  let element = document.querySelector('#foo');
  if (element) {
    let observer = new IntersectionObserver((entries, self) => {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          // Fetch more things from an API or something
        }
      });
    }, { rootMargin: '0px 0px 200px 0px' });

    observer.observe(element);
  }
}, []);
  1. Firing async redux actions, especially for fetching initial objects from a remote server.
import { useDispatch, useSelector } from 'react-redux';  
import { getThings } from './actions';

const Component = () => {  
  const dispatch = useDispatch();
  const things = useSelector((state) => state.things);
  const [page, setPage] = useState(1);

  useEffect(() => {
    if (!things || things.length < page * 10) {
      dispatch(getThings({ page, limit: 10 }));
    }
  }, [page]);

  return (/* <jsx> */);
};
  1. To trigger timeouts or intervals. For example, to automatically hide a message after a period of time or to poll a server for new data.
const [visible, setVisible] = useState(true);

useEffect(() => {  
  setTimeout(() => setVisible(false), 4000);
}, []);

And there are many, many more practical applications for useEffect. It's an indispensable tool for the functional component project, and I hope this brief overview has given you the confidence to start using it in your own projects. If not - if I've failed to explain something properly - please comment below, and I will do my best to answer any questions. Thanks for reading.