Setting up a React app with styled-components to consume a Node API
Marlon Souza
Posted on October 10, 2020
Hey there,
In the last tutorial, we learned how to set up a REST API with node.js and express. In this tutorial, we are going to set up a React App with styled-components to connect to the API from the last tutorial.
I hope you can learn something from this tutorial and I can learn something with your feedback.
Before start, you need to have the back-end installed and also running. You could read this tutorial or just clone this project and follow the instructions.
Requirements:
- Yarn (Documentation).
- Visual Studio Code (Download).
So let’s get started!
What is React?
React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.
Reference
Starting the project:
The first step will be creating the project using the toolchain Create React App:
$ yarn create react-app reactjs-styledcomponents-setup && cd reactjs-styledcomponents-setup
Why do we need to use Create React App?
This toolchain provides a development environment to help us to have a better experience and not wasting time configuring many build tools in every new project.
You can have more information here.
You might have these files in your folder:
We can delete some files that we won't use in this tutorial:
$ cd src && rm -Rf App.test.js logo.svg serviceWorker.js setupTests.js App.css
Open the index.js file and then delete the following lines:
...
import * as serviceWorker from './serviceWorker';
...
serviceWorker.unregister();
Also, we need to delete the following lines in the App.js file:
...
import logo from './logo.svg';
...
<img src={logo} className="App-logo" alt="logo" />
We can start our project now, you should go to your console to digit the command line below:
$ yarn start
We deleted the unnecessary files, we can move forward to the next step.
ReactDOM
The react-dom package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.
Reference
Ok, we learned what is a react-dom but you might be thinking what is DOM?
What is DOM?
The Document Object Model (DOM) is a programming interface for HTML and XML documents that will allow the javascript to add/change/remove HTML elements, attributes, CSS styles, and events.
You can read more here.
We learned about react-dom and DOM, we will look at how to use React Dom.
Open the index.js file, it can be found in the src folder. You will see some lines and one of these lines will be the ReactDOM.render().
Basically, the react-dom package provides some specifics DOM methods, and render() will be one of the methods that will be used in this tutorial.
render():
Render a React element into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).
Reference
In this case, the component App is the React element that will be rendered into the DOM in the supplied container that contains the id root and accomplishes that we are using document.getElementById('root').
What is getElementById()?
This method returns the element from the HTML document based on the id attribute.
You will be able to find the div tag with the id root opening the file index.html, this HTML file will be found in the public folder.
Probably you saw the React.StrictMode when you opened the index.js and I believe you are thinking... "What is it that?". The React.StrictMode won't be useful in this tutorial but it is in the index.js for default, and I won't mind keeping it and also explain how works.
What is React.StrictMode?
In our development journey is very common to find problems in the application, this tool will highlighting potential problems in development mode adding warnings at runtime. If you want to use this tool you just need to put it around the components.
The warnings will appear on your browser console.
The benefits of this tool:
- Identifying components with unsafe lifecycles;
- Warning about legacy string ref API usage;
- Warning about deprecated findDOMNode usage;
- Detecting unexpected side effects;
- Detecting legacy context API.
You can have more information here.
We learned about react-dom and we can move forward to the next step of this tutorial.
Creating a basic page to consume our API
We are going to create a page to look at how the Http requests work on the client-side.
This part of the tutorial will be great because we will see examples of how the web application consumes an API.
We need to install the axios library:
$ yarn add axios
Why do we need to install this library?
This library will provide us the HTTP request that we will use during this tutorial.
Open the App.js and add the following lines:
import axios from 'axios';
...
function App() {
const api = axios.create({
baseURL: 'http://localhost:3333',
});
return(
...
)
}
In the code above, we are creating an instance named api to receive all the methods and avoid using the same URL for all requests that will be created.
From now on, we are going to write some examples using HTTP get, post, put, delete requests.
GET:
In this example, we will receive the users from our API, and then we are going to show these users in the browser.
Add the following lines in App.js:
import React, { useEffect, useState } from 'react';
...
function App() {
const [users, setUsers] = useState([]);
...
useEffect(()=>{
async function getUsers(){
const response = await api.get('users');
const newArray = response.data.map((item) => ({
id: response.data.indexOf(item),
user: item
}))
setUsers(newArray);
}
getUsers();
// eslint-disable-next-line react-hooks/exhaustive-deps
},[])
return(
...
)
}
In the code above, we have a function responsible to get the users from the API and then to save these users using the setUsers from the state hook.
If this is your first time using React Hook, you might be thinking... "What is a Hook? and What does useEffect and useState do"?
What is a Hook?
Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don’t work inside classes — they let you use React without classes.
Reference.
This tutorial will only cover two basics Hooks but if you are interested in all the Hooks available so you can get more information here.
What does useEffect do?
By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.
Reference
Only thinking in performance, useEffect is amazing because React will prioritize the rendering of your application before fetching the data. Maybe we have many users to receive from API that it could affect negatively the application if we need to load everything at the same time but this won't happen using UseEffect.
What does calling useState do?
This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.
Reference
The useState will help us to store the array received from the API because we are going to use this array in other parts of our code.
Right now we need to create the page to show the users on the browser.
The first step will be the styled-components installation.
$ yarn add styled-components
This framework will allow us to write HTML elements with CSS as a component. Styled-components give us the freedom to use the same CSS code in more than one React component.
You can read more here.
We need to create the styles.js file inside of the src folder:
$ touch styles.js
Open the styles.js and add the following lines:
import styled from 'styled-components';
export const Container = styled.ul`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
max-height: 100%;
height: 500px;
list-style: none;
li{
margin-top: 10px;
}
`;
export const Input = styled.input`
height: 28px;
width: 200px;
margin-right: 5px;
padding-left: 4px;
border: 0.5px solid #eee;
border-radius: 4px;
`;
The structure is different from than classic CSS document because we are using styled-component to create a ul tag with some CSS properties and then we are exporting to the Container variable.
Input is the same but it has a different tag and CSS properties.
In our App.js we need to add the following lines:
...
import { Container, Input } from './styles'
function App() {
...
return(
<Container>
{users.map((item)=>(
<li key={item.id}>
<Input value={item.user} />
</li>
))}
</Container>
)
}
We are going to use the input element to show the values and also edit them. You will understand the reason for using the same element to show the value and edit it in the next step of the tutorial, where we will create the edit function.
Open your browser to access your React App (http://localhost:3000/), you might have something like this:
It is a very modest page but it is possible to show all the users on the browser.
Remind you: You need to have the back-end running. At the beginning of the page, I gave you some options on how to get the back-end from this tutorial.
PUT:
We will create one example using the PUT request to change the user name.
The first step is to add some lines in styles.js:
...
export const Button = styled.button`
margin-left: 5px;
border: 0;
border-radius: 5%;
background: ${props=> props.backgroundColor};
color: #333;
height: 30px;
width: 70px;
cursor: pointer;
`;
And now, we need to add the following lines in App.js:
...
import { Container, Input, Button } from './styles'
function App() {
const [edit, setEdit] = useState({isEdit: false, id: 0});
...
function updateUser(e, id){
const userUpdated = users.map((item)=> {
return item.id === id ? {id: item.id, user: e.target.value} : item;
});
return setUsers(userUpdated);
}
const handleInputChange = async (id) =>{
await api.put(`users/${id}`, { user: users[id].user });
}
return(
<Container>
{users.map((item)=>(
<li key={item.id}>
<Input value={item.user} onChange={(e)=> updateUser(e, item.id)} disabled={edit.isEdit && edit.id === item.id ? false : true}/>
<Button onClick={()=> handleInputChange(item.id)} style={{display: edit.isEdit && edit.id === item.id ? null : 'none'}} backgroundColor={'#C0F9B6'}>Submit</Button>
<Button onClick={()=> setEdit({isEdit: !edit.isEdit, id: item.id })} backgroundColor={'#87B6FD'}>Edit</Button>
</li>
))}
</Container>
)
}
Replace the input from the first example to this new input.
We are using the map method in the updateUser function to change the object user based on the id so we can show the new values in the input field every time the letters were typed.
In the arrow function handleInputChange, we will send the user object using the api instance to call the HTTP Put request.
The id is a parameter necessary to update a user based on the array index.
Open your browser to access your React App (http://localhost:3000/) and try to edit one user, you might have something like this:
DELETE:
We learned how to edit but now we want to delete, so we will use the HTTP delete request to remove the users that we don't want to keep in our application.
Add the following lines in App.js:
...
function App() {
...
const handleDelete = async(id)=>{
const response = await api.delete(`users/${id}`);
const newArray = response.data.map((item) => ({
id: users.indexOf(item),
user: item
}));
setUsers(newArray)
}
return(
<Container>
{users.map((item)=>(
<li key={item.id}>
...
<Button onClick={()=> handleDelete(item.id)} backgroundColor={'#FA6C6C'}>Delete</Button>
</li>
))}
</Container>
)
}
The delete button will execute the arrow function handleDelete every time is pressing. This arrow function will delete the user using the api instance to call the HTTP delete request.
The id is a parameter necessary to delete a user based on the array index.
Open your browser to access your React App (http://localhost:3000/) and try to delete a user, you might have something like this:
POST:
I left the best part for last.
Finally, we will look at how to add more users using the HTTP Post request.
We need to add more lines in our styles file:
...
export const AddUser = styled.div`
display: flex;
justify-content: space-around;
margin: 20px auto;
width: 20%;
`;
And then we need to add the following lines in App.js:
...
import { Container, Input, Button, AddUser } from './styles'
function App() {
...
async function handleAddUser(){
const response = await api.post('/users', { user: addUsers})
const newArray = response.data.map((item) => ({
id: response.data.indexOf(item),
user: item
}));
setUsers(newArray)
}
return(
<Container>
{users.map((item)=>(
...
))}
<AddUser>
<Input onChange={(e)=> setAddUsers(e.target.value)} placeholder="Type the user name..."/>
<Button onClick={()=> handleAddUser()} backgroundColor={'#C0F9B6'}>Add</Button>
</AddUser>
</Container>
)
}
The setAddUsers will save the words typed in the input element and then the handleAddUser function will send the user object using the api instance to call the HTTP post request and also it will use the map method to create a new array.
Open your browser to access your React App (http://localhost:3000/) and try to create a new user, you might have something like this:
Conclusion
We learned how to set up a React project with styled-components and make some HTTP requests on the client-side.
Clearly, all the changes we made to the array will disappear when the back-end is restarted because we are not saving in a database but it was a good example of how to consume an API.
I am proud of you and myself because we finished another tutorial. I hope I have contributed to your long trajectory of knowledge.
You can access the project here
See you in the next tutorial!
Posted on October 10, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.