Last active
May 9, 2024 11:56
-
-
Save aneurysmjs/4176d8627b1ce79de30ffde342fee33b to your computer and use it in GitHub Desktop.
some considerations when using useEffect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
useEffect(() => { | |
// componentDidMount ? | |
}, []); | |
useEffect(() => { | |
// componentDidUpdate ? | |
}, [foo, bar]); | |
useEffect(() => { | |
return () => { | |
// componentWillUnmount ? | |
}; | |
}, []); | |
/** | |
* useEffect is not a lifecycle hook | |
* | |
* while you could use it that way and it is expected to run | |
* at the exact same time as you mount your component, change and unmount | |
* it's not the way that you should be thinking about things. | |
* | |
* the mental model is synchronization. Not lifecycle. | |
* | |
* the question is not "when does this effect runs" the question is "with which state | |
* does this effect synchronize with" | |
* | |
* useEffect(fn) // all state | |
* useEffect(fn, []) // no state | |
* useEffect(fn, [these, states]) | |
*/ | |
useEffect(() => { | |
if (foo && bar && (baz || quox)) { | |
doSomething(); | |
} else { | |
doSomethingElse(); | |
} | |
}, [foo, bar, baz, quox]); | |
/** | |
* Dependencies are the wrong mental model for effects | |
* | |
* we want effects to execute when things happen and not | |
* exactly when things change. | |
*/ | |
/** | |
* you don't need useEffect for transforming data. | |
* | |
* we want effects to execute when things happen and not | |
* exactly when things change. | |
*/ | |
function Cart() { | |
const [items, setItems] = useState<{ id: number; price: number }[]>([]); | |
const [total, setTotal] = useState(0); | |
useEffect(() => { | |
setTotal(items.reduce((accum, { price }) => accum + price, 0)); | |
}, [items]); | |
// ... | |
} | |
// instead you just could calculate on a render/re-render | |
function Cart() { | |
const [items, setItems] = useState<{ id: number; price: number }[]>([]); | |
const total = items.reduce((accum, { price }) => accum + price, 0); | |
// ... | |
} | |
/** | |
* you don't need useEffect for fetching. | |
*/ | |
function Products() { | |
const [isLoading, setIsLoading] = useState(false); | |
const [hasError, setHasError] = useState(false); | |
useEffect(() => { | |
async function fetchProducts() { | |
setIsLoading(true); | |
try { | |
const response = await fetch('https://products.com'); | |
const products = await response.json(); | |
setIsLoading(false); | |
return products | |
} catch (err) { | |
setHasError(true); | |
} | |
} | |
fetchProducts(); | |
}, []) | |
// ... | |
} | |
// instead fetch as you render | |
function Products() { | |
const { data, isLoading } = useQuery({ | |
queryKey: ['products'], | |
queryFunction: () => axios.get('https://products.com'), | |
}); | |
// ... | |
} | |
/** | |
* cancel a promise on `cleanup` | |
*/ | |
function Products() { | |
const [data, setData] = useState(); | |
useEffect(() => { | |
const controller = new AbortController(); | |
axios.get('https://products.com', { signal: controller.signal }) | |
.then(res => { | |
setData(res.data); | |
}); | |
return () => controller.abort(); | |
}, []); | |
/// ... | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment