So far our reducers have simply been used to update a single value passed in with an action. In this lesson we'll practice adding more logic into a reducer, which is recommended in the redux style guide. We will do this by removing a hard coded list of supported currencies to update based on the API call that we make.
One of the techniques we'll cover is using curly braces ({
and }
) to create blocks inside of our switch
statement, so that the variables we make while responding to an action don't leak into the outer scope.
Instructor: [0:00] If you go into exchangerate.js, you'll see that we import supportedCurrencies and then pass it directly into currencyCodePicker. Instead, let's put supportedCurrencies in our Redux store.
[0:13] Go back into rates.js. Copy the supportedCurrencies array down here into initial state, getting rid of the exported variable. Let's add a selector, export const getSupportedCurrencies = state(state.rates.supportedcurrencies).
[0:31] We now have a selector. We can now go back into currencyCodePicker. Import the useSelector method and type const supportedCurrencies = useSelector. Then, we can also import getSupportedCurrencies. With that in our selector and this out of our props, we'll now only show the supported currencies in our dropdown list.
[0:54] That's not the only problem that we have. SupportedCurrencies was also being used inside the change currency code thunk. One solution for that would be to use getState here and save the state into a variable. Then, grab the supported currencies from the state using our selector, getSupportedCurrencies(state).
[1:12] Now that fixes the problem that we had with supported currencies, but there is still the issue of this list being hardcoded. While it's fine to send in an initial hardcoded list to populate our dropdown and to send to the API, once we get the API call back, it'll be helpful to update this list to ensure that only currency codes found in our response are actually included in the list.
[1:32] In order to do that, we can go into our ratesReceived section of our reducer. We're going to wrap this case in curly braces. The curly braces will allow us to have variables who only have scope for this block and won't affect anything else in this function, or even in this switch statement.
[1:47] We can type const codes = {object.keys(action.payload)}. That gives us a list of the new currency codes, and we can add those here, supportedCurrencies: codes.
[2:02] As we refresh the page, it's hard to tell, but you'll notice each time we click on a different currency, our list gets smaller and smaller. That's because our API doesn't return our current currency code. It only returns the currency codes for which it provides conversion rates, but it doesn't provide a conversion code for your current currency.
[2:22] We have to add that into our list. We can do that by doing object.keys.concat. Then, we need to get the current currency code. We already have access to state, so we can say state.currencyCode.
[2:35] Refreshing the page, you'll notice that we have one, two, three, four, five here. One, two, three, four, five, six here, which is correct. If I click through the different codes, they are updating. They are not losing anything.
[2:49] In this lesson, I wanted to emphasize having more complex logic in our reducers. A good way to do that is to wrap them with these curly braces, which allows you to create variables which don't leak into the outer scope. We also took another look at using getState and passing that into selectors within a thunk.
[3:08] In modern Redux, it's highly encouraged to put a lot of logic in your reducers, as long as you follow the rules of not modifying the existing state and not doing anything in here that has side effects.
The React docs have a great article on where to get your keys from: https://beta.reactjs.org/learn/rendering-lists#where-to-get-your-key
The logic added to this lesson for the rates/ratesReceived
action isn't necessary anymore since we're now using a local mock API setup. I think
index.js:1 Warning: Encountered two children with the same key,
USD
. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause childr