title: React Hooks multiple alerts with individual countdowns
body: <p>I've been trying to build an React app with multiple alerts that disappear after a set amount of time. Sample: <a href="https://codesandbox.io/s/multiple-alert-countdown-294lc" rel="nofollow noreferrer">https://codesandbox.io/s/multiple-alert-countdown-294lc</a></p>
  
  <pre><code>import React, { useState, useEffect } from "react";
  import ReactDOM from "react-dom";
  
  import "./styles.css";
  
  function TimeoutAlert({ id, message, deleteAlert }) {
    const onClick = () =&gt; deleteAlert(id);
    useEffect(() =&gt; {
      const timer = setTimeout(onClick, 2000);
      return () =&gt; clearTimeout(timer);
    });
    return (
      &lt;p&gt;
        &lt;button onClick={onClick}&gt;
          {message} {id}
        &lt;/button&gt;
      &lt;/p&gt;
    );
  }
  let _ID = 0;
  function App() {
    const [alerts, setAlerts] = useState([]);
    const addAlert = message =&gt; setAlerts([...alerts, { id: _ID++, message }]);
    const deleteAlert = id =&gt; setAlerts(alerts.filter(m =&gt; m.id !== id));
    console.log({ alerts });
    return (
      &lt;div className="App"&gt;
        &lt;button onClick={() =&gt; addAlert("test ")}&gt;Add Alertz&lt;/button&gt;
        &lt;br /&gt;
        {alerts.map(m =&gt; (
          &lt;TimeoutAlert key={m.id} {...m} deleteAlert={deleteAlert} /&gt;
        ))}
      &lt;/div&gt;
    );
  }
  
  const rootElement = document.getElementById("root");
  ReactDOM.render(&lt;App /&gt;, rootElement);
  </code></pre>
  
  <p>The problem is if I create multiple alerts, it disappears in the incorrect order. For example, test 0, test 1, test 2 should disappear starting with test 0, test 1, etc but instead test 1 disappears first and test 0 disappears last.</p>
  
  <p>I keep seeing references to useRefs but my implementations don't resolve this bug.</p>
  
  <hr>
  
  <p>With @ehab's input, I believe I was able to head down the right direction. I received further warnings in my code about adding dependencies but the additional dependencies would cause my code to act buggy. Eventually I figured out how to use refs. I converted it into a custom hook.</p>
  
  <pre><code>function useTimeout(callback, ms) {
    const savedCallBack = useRef();
    // Remember the latest callback
    useEffect(() =&gt; {
      savedCallBack.current = callback;
    }, [callback]);
    // Set up timeout
    useEffect(() =&gt; {
      if (ms !== 0) {
        const timer = setTimeout(savedCallBack.current, ms);
        return () =&gt; clearTimeout(timer);
      }
    }, [ms]);
  }
  </code></pre>