Skip to content

Instantly share code, notes, and snippets.

@aneurysmjs
Last active May 9, 2024 11:56
Show Gist options
  • Save aneurysmjs/4176d8627b1ce79de30ffde342fee33b to your computer and use it in GitHub Desktop.
Save aneurysmjs/4176d8627b1ce79de30ffde342fee33b to your computer and use it in GitHub Desktop.
some considerations when using useEffect
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