visit
$ yarn create react-app rates
$ yarn start
Install the swr and unfetch libraries. It helps to easily fetch API.
$ yarn add swr unfetch
// src/App.js
import React from "react";
import "./App.css";
import fetch from "unfetch";
const API_URL = "//api.exchangeratesapi.io";
const fetcher = async path => {
const res = await fetch(API_URL + path);
const json = await res.json();
return json;
};
// function App...
Add useSWR in App component to fetch data
import React from "react";
import "./App.css";
import fetch from "unfetch";
import useSWR from "swr";
// API_URL = ...
// const fetcher = ...
function App() {
const { data: currencies } = useSWR("/latest?base=EUR", fetcher);
return <div>Welcome to your Currency exchange app!</div>;
}
Now we have the currencies rates in currencies.rates variable.
To see the JSON data of currencies rates you can open the API url directly into your browser:The ?base=EUR query is used to get all rates relative to EUR currency.
For ui, we will use the material-ui design system. Install it:
$ yarn add @material-ui/core
Create the UI for our currency exchange app in the App component.
// ...
import {
Container,
Paper,
Grid,
TextField,
Select,
MenuItem
} from "@material-ui/core";
// ...
function App() {
const { data: currencies } = useSWR("/latest?base=EUR", fetcher);
if (!currencies) {
return null;
}
return (
<Container className="currency-exchange-container" fixed>
<h1>Currency exchange</h1>
<Paper
className="currency-exchange-paper"
variant="outlined"
elavation={1}
>
<Grid container spacing={3}>
<Grid item xs={6}>
<TextField type="number" />
</Grid>
<Grid item xs={6}>
<TextField type="number" />
</Grid>
<Grid item xs={6}>
<Select>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
<Grid item xs={6}>
<Select>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
</Grid>
</Paper>
</Container>
);
}
<Select>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
if (!currencies) {
return null;
}
Add some styles to App.css
h1 {
font-weight: 300;
color: #636363;
margin-bottom: 3rem;
}
.currency-exchange-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.currency-exchange-paper {
max-width: 350px;
padding: 30px 30px 40px 30px;
}
.MuiInput-root {
width: 100%;
}
Now we add the inputs state to our App component
function App() {
const { data: currencies } = useSWR("/latest?base=EUR", fetcher);
const [fromValue, setFromValue] = useState(1);
const [toValue, setToValue] = useState(1);
const [fromCurrency, setFromCurrency] = useState("EUR");
const [toCurrency, setToCurrency] = useState("EUR");
const handleFromCurrencyChange = e => {
setFromCurrency(e.target.value);
};
const handleToCurrencyChange = e => {
setToCurrency(e.target.value);
};
const handleFromValueChange = e => {
setFromValue(parseFloat(e.target.value));
};
const handleToValueChange = e => {
setToValue(parseFloat(e.target.value));
};
if (!currencies) {
return null;
}
return (
<Container className="currency-exchange-container" fixed>
<h1>Currency exchange</h1>
<Paper
className="currency-exchange-paper"
variant="outlined"
elavation={1}
>
<Grid container spacing={3}>
<Grid item xs={6}>
<TextField
type="number"
value={fromValue}
onChange={handleFromValueChange}
/>
</Grid>
<Grid item xs={6}>
<TextField
type="number"
value={toValue}
onChange={handleToValueChange}
/>
</Grid>
<Grid item xs={6}>
<Select value={fromCurrency} onChange={handleFromCurrencyChange}>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
<Grid item xs={6}>
<Select value={toCurrency} onChange={handleToCurrencyChange}>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
</Grid>
</Paper>
</Container>
);
}
const convertFromTo = () => {
const fromRate =
fromCurrency === "EUR" ? 1 : currencies.rates[fromCurrency];
const valueInEur = fromValue / fromRate;
const toRate = toCurrency === "EUR" ? 1 : currencies.rates[toCurrency];
setToValue(valueInEur * toRate);
};
const convertToFrom = () => {
const toRate = toCurrency === "EUR" ? 1 : currencies.rates[toCurrency];
const valueInEur = toValue / toRate;
const fromRate =
fromCurrency === "EUR" ? 1 : currencies.rates[fromCurrency];
setFromValue(valueInEur * fromRate);
};
useEffect(() => {
convertFromTo();
}, [fromValue, toCurrency]);
useEffect(() => {
convertToFrom();
}, [toValue, fromCurrency]);
Here is a full App.js file
import React, { useState, useEffect } from "react";
import "./App.css";
import fetch from "unfetch";
import useSWR from "swr";
import {
Container,
Paper,
Grid,
TextField,
Select,
MenuItem
} from "@material-ui/core";
const API_URL = "//api.exchangeratesapi.io";
const fetcher = async path => {
const res = await fetch(API_URL + path);
const json = await res.json();
return json;
};
function App() {
const { data: currencies } = useSWR("/latest?base=EUR", fetcher);
const [fromValue, setFromValue] = useState(1);
const [toValue, setToValue] = useState(1);
const [fromCurrency, setFromCurrency] = useState("EUR");
const [toCurrency, setToCurrency] = useState("EUR");
const handleFromCurrencyChange = e => {
setFromCurrency(e.target.value);
};
const handleToCurrencyChange = e => {
setToCurrency(e.target.value);
};
const handleFromValueChange = e => {
setFromValue(parseFloat(e.target.value));
};
const handleToValueChange = e => {
setToValue(parseFloat(e.target.value));
};
const convertFromTo = () => {
const fromRate =
fromCurrency === "EUR" ? 1 : currencies.rates[fromCurrency];
const valueInEur = fromValue / fromRate;
const toRate = toCurrency === "EUR" ? 1 : currencies.rates[toCurrency];
setToValue(valueInEur * toRate);
};
const convertToFrom = () => {
const toRate = toCurrency === "EUR" ? 1 : currencies.rates[toCurrency];
const valueInEur = toValue / toRate;
const fromRate =
fromCurrency === "EUR" ? 1 : currencies.rates[fromCurrency];
setFromValue(valueInEur * fromRate);
};
useEffect(() => {
convertFromTo();
}, [fromValue, toCurrency]);
useEffect(() => {
convertToFrom();
}, [toValue, fromCurrency]);
if (!currencies) {
return null;
}
return (
<Container className="currency-exchange-container" fixed>
<h1>Currency exchange</h1>
<Paper
className="currency-exchange-paper"
variant="outlined"
elavation={1}
>
<Grid container spacing={3}>
<Grid item xs={6}>
<TextField
type="number"
value={fromValue}
onChange={handleFromValueChange}
/>
</Grid>
<Grid item xs={6}>
<TextField
type="number"
value={toValue}
onChange={handleToValueChange}
/>
</Grid>
<Grid item xs={6}>
<Select value={fromCurrency} onChange={handleFromCurrencyChange}>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
<Grid item xs={6}>
<Select value={toCurrency} onChange={handleToCurrencyChange}>
<MenuItem value={"EUR"}>EUR</MenuItem>
{Object.keys(currencies.rates).map((rate, key) => (
<MenuItem key={key} value={rate}>
{rate}
</MenuItem>
))}
</Select>
</Grid>
</Grid>
</Paper>
</Container>
);
}
export default App;