The useEffect hook provides a way for components to declaratively state side effects that need to be run. By modifying the dependency array you can simulate certain React lifecycle methods such as constructor
/componentDidMount
and componentDidUpdate
and componentWillUnmount
. The useEffect
hook is always called after the first render of your component and then any time its dependencies change.
componentDidMount() {
fetchData();
}
Is functionally equivalent to:
useEffect(() => {
fetchData();
}, [])
Likewise this common approach:
componentDidUpdate(prevProps) {
if (this.props.someProp !== prevProps.someProp) {
handleChange();
}
}
Can be replaced with the following hook:
useEffect(() => {
handleChange();
}, [someProp);
There is also a cleanup phase that happens with hooks. If you return a function inside of a hook it will be executed just before the function is unmounted. This is similar to the componentWillUnmount
hook and is explained in detail here:
https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup
Jamund Ferguson: [0:03] Open up ExchangeRate.js and import { useEffect } from "react". Now convert your class component to a function component. Type export function ExchangeRate, use parentheses instead of extends, and let's convert any of the methods into function declarations -- function componentDidUpdate, function getLatestExchangeRates.
[0:21] Let's take our render() method and bring its contents to the body of our component. For now, let's comment out both the constructor and componentDidUpdate. Lastly, we'll need to bring over our props, currencyCode, updateRates and supportedCurrencies. These are all coming from Redux. We'll stick them right there in our function declaration.
[0:45] Now we have a function component for ExchangeRate. It's taking all the same props as before, but when I refresh the page, you'll see that it won't actually get a full list of Exchange Rates. Instead, I only get one, USD. If you recall, in our rateReducer, we set the default rate USD for 1., or one times the amount.
[1:04] We've got our default rate in there, but we need to get the actual exchange rates, before we're doing that in our constructor, and in the componentDidUpdate method. Now we can use hooks to do that.
[1:13] Type useEffect() and pass in an arrow function. For the second argument, which is the dependency array, for now we'll just put an empty array, which means only run this effect the first time you render the component. Inside of that, we'll place our getLatestExchangeRates() function.
[1:32] With that in place, you can see that we now have our list of Exchange Rates. However, when I change the currency code, the Exchange Rates list doesn't change. We used to have that with our componentDidUpdate and we compare the old and new version of currencyCode, and then if it changes, we'll decide to call getLatestExchangeRates.
[1:49] With useEffect, we can simply put currencyCode in our dependency array, and now, anytime the currency code changes, it will also rerun getLatestExchangeRates.
[2:00] With our updated useEffect hook in place, we can get rid of both our constructor and our componentDidUpdate method and our function fully responds to changes in currency code to get the latest exchange rates.
Hey V, here is a link to stack overflow explaining the reason for needing to pass the function into the useEffect dependency array. https://stackoverflow.com/questions/62601538/passing-a-function-in-the-useeffect-dependency-array-causes-infinite-loop
The redux-linting has a warning:
React Hook useEffect has a missing dependency: 'getLatestExchangeRates'. Either include it or remove the dependency array. eslint(react-hooks/exhaustive-deps)
I would be curious why currencyCode is not sufficient to satisfy the minimum.