I've been tackling a coding challenge from the Scrimba front-end development course.
The challenge is this:
Given some boilerplate HTML and CSS, create a working currency converter.
The HTML comprises an input box for a currency amount, two further input boxes for base and target currencies, and a final input box for the exchange rate. (full challenge here: Scrimba Challenge)
This is the basic form we were provided with:
The easiest and quickest way to complete the challenge would be to grab the value from the amount box, multiply the amount by the inputted exchange rate, and display it next to the inputted target currency code. But as no one manually inputs currency codes and exchange rates these days, it would make a pretty pointless app. I decided that even though it's just for practice/portfolio, I'll make an app that's useful with decent UX (or do my best to follow sound design principles at least!) and make sure it's accessible and responsive. I decided to use REACT to complete the task.
Before starting, I broke the challenge down into it's constituent parts.
- 1. get exchange rates from an API
- 2. get a list of currency codes
- 3. plan the REACT components I'll need
- 4. code it out
- 5. style it - check accessibility
- 6. double check accessibility with online tool
The exchange rates. There are several promising looking APIs with currency data. I used exchangeratesapi.io, which does exactly what it says on the tin. A fetch request easily returned all data I would need.
A got the currency codes from Fluidbyte on GitHub. Many thanks to him, now users can select their chosen currencies from dropdown select boxes. The data set included currency name, plural name, currency code(e.g. GBP), current value, and symbol(£, $ etc).
React is easiest when you plan ahead! I decided to separate the intelligent (logic) from the dumb (just UX) as much as possible when creating components. I decided to go for:
- 1. an App component to anchor the app
- 2. a Header component for logo, name and headline text
- 3. a Form component to handle the inputs
- 4. a Datafetcher component to handle the API and the maths
- 5. an Output component to display the results
- 6. a Social component for a social media banner
- 7. a Footer component for the footer text.
Only number 4, the Datafetcher
, contained serious logic - although there was some logic in Form
to populate the select boxes and to handle changes and clicks on the form.
All of the components were functional components, and I used the useState hook where holding state was necessary and props to pass data from Form to Datafetcher and then on to Output.
4.Everything went pretty smoothly with the REACT until I tried to dynamically create the select boxes for the currency codes, which I had as JSON. However I tried to do it (for e.g. mapping the data to a const and rendering the const - well, it's an object, so that was doomed to failure), REACT kept throwing errors.
The answer was deceptively simple (thanks Google!):
In your return statement you put the opening and closing <select>
tags of your input. Between the tags you call a function, mine was {createCurrencySelectInput()}
. That function uses a for/in loop to go through the JSON data and push a <option key={whateverKey}>my data</option>
JSX component to an array (remembering to include a key so as to avoid REACT warnings). Make sure the function returns the array, and it works perfectly.
Here's the function:
function createCurrencySelectInput() {
let items = []
for (let item in data) {
items.push(<option key={item.id} value={item}>{item}
</option>)
}
return items
}
...and the rendered tags and function call.
<select onChange={handleChange} myProps="someProps">
{createCurrencySelectInput()}
</select>
I used CSS grid to style the App. As ever, I am sure I made it more complicated than it need be!
I ran through accessibility and checked my colour scheme using an online checker from color-blindness.com. I had concerns about the blue and yellow/green combination but all was fine!
Pretty happy with the end result:
Top comments (1)
really nice way of thinking ahead, good path of design. just a tip, maybe run the 'We can offer' response value in Math.round() function so you get a rounded number