An effect listing a value in its dependencies and setting that value in its body is an infinite loop, and the analyser that suggested adding the dependency is what led there.
// loops
useEffect(() => {
setTotal(items.reduce((a, i) => a + i.price, 0))
}, [items, total])
// and the version that is not a loop and is still wrong:
useEffect(() => {
setTotal(items.reduce((a, i) => a + i.price, 0))
}, [items])
// because it is a derivation, and derivations are not effects
const total = useMemo(
() => items.reduce((a, i) => a + i.price, 0), [items])
The second version works and costs an extra render every time items changes, which is the point worth making — an effect that only sets state from props or other state is computing a value in the wrong place. The rule that removes the whole category is that effects are for synchronising with something outside React, and a total is not outside React.