score:1

Accepted answer
const Item = ({ id, updateTime }) => {
  const [showHighlight, setShowHighlight] = React.useState(false);

  // By putting `updateTime` in the dependency array of `useEffect,
  // we re-trigger the highlight every time `updateTime` changes.
  useEffect(() => {
    if (updateTime) {
      setShowHighlight(false);
      setTimeout(() => {
        setShowHighlight(true);
      }, 10);
    }
  }, [updateTime]);

  return <div className={showHighlight ? "updated" : ""}>Item {id}</div>;
};

const App = () => {
  // tracking the update times at the top level
  const [updateTimes, setUpdateTimes] = React.useState({});

  // ...
        <Item key={id} id={id} updateTime={updateTimes[id]} />

  // ...
        <button
          onClick={() => {
            setUpdateTimes({ ...updateTimes, [id]: Date.now() });
          }}
        >
   // ...
}

score:1

  const [updateTimes, setUpdateTimes] = React.useState({});

  // ...

        <Item key={id} id={id} updateTime={updateTimes[id]} />

  // ...
        <button
          onClick={() => {
            setUpdateTimes({ ...updateTimes, [id]: Date.now() });
          }}
        >

   // ...

score:2

const [waitAndHoldId, setWaitAndHoldId] = React.useState([]);

useEffect(() => {
  setLastUpdatedId(waitAndHoldId[0]);
}, [waitAndHoldId]);

function resetLastUpdatedId(id) {
  if (lastUpdatedId !== id) {
    // If it's different: just set it and we are done.
    setLastUpdatedId(id);
  } else {
    // If not:
    setWaitAndHoldId([id]);

    /**
     * Setting an array will always trigger the useEffect (even if
     * it remains the same). The useEffect will take an instant to
     * run. Meanwhile, force the `lastUpdatedId` to reset with a
     * different value (e.g.: undefined).
     */

    // This will run before the useEffect.
    setLastUpdatedId(undefined);
  }
}

// ...

<button onClick={() => resetLastUpdatedId(id)}>
  Update item {id}
</button>

Related Query

More Query from same tag