Day purposes
β Create your own User Interface (UI) with React and Chakra UI.
β Structure your UI.
β Test your UI.
β Make your UI responsive.
React is a Javascript library to build user interfaces.
What is a user interface?
A user interface (UI) is the point at which humans interact with a computer, a website or an application.
For instance, your terminal is a user interface.
What does this Javascript library allow us to do?
Thanks to React, you can build React Components, which is a Javascript function that returns a Javascript object representing a DOM element in memory.
All these DOM elements in memory compose the Virtual DOM.
π‘ DOM stands for Document Object Model, which is the HTML representation of a web page. As a consequence, a DOM element is a part of the HTML representation of a web page.
This Virtual DOM is a copy of the Real DOM.
- The Real DOM is the HTML representation of the web page that the user sees. It's updated by queries
- The Virtual DOM is a copy of the Real DOM. It's automatically updated when the state of a React Component is updated. It automatically updates the Real DOM.
In fact, this is why React is called React, it's reactive to changes of state to automatically updates the DOM π
When you create a React component, you can specify when its states should change.
This is the magic. You no more need to update the Real DOM by hand! πͺ
Maybe you don't understand why this is awesome. It's because you haven't played yet with the Real DOM.
If you want, at the end of the day, try to build the same application without React, then you will understand π Here's the official DOM documentation.
How to use React the right way?
There are two rules to follow:
- Build a tree of components
- Build a React Component for each element of your UI
Here's an example:
Each number corresponds to a React Component.
You can call React Components inside another React Component π
If you follow this until the end, you will get a single page app.
π‘ This means that your app is a single React Component, composed of React Components.
Okay, this is great for developers! How about users?
Building the Real DOM takes time.
Thus when a web page is loaded, the user have to wait a bit.
However if you use React well, you build the Real DOM only one time (when the first page is loaded), then you just update it.
As a consequence, by using React you give your users a more fluid experience π₯
In your pool repository, create a new directory for the day05
:
mkdir -p day05
Then, create a new React project with Typescript:
npx create-react-app artists-book --template typescript
Don't worry if you see vulnerabilities after this command, it's a false positive.
If you are curious about it take a look at this issue π
To verify that everything is ok, run the following commands:
# Move to your project
cd artists-book
# Start the server
npm start
If you get a page with the React logo spinning, then you can continue π
Before going further, take a moment to read the React Getting Started and its tutorials.
Make sure to understand what is a functional component as you'll have to use it for every component you'll create.
It's important to take at least 30 minutes to read these tutorials, it will save you a lot of time.
Don't also hesitate to ask the staff if you don't understand certain concepts π
Now that you understand the core concepts of React, it's time to lay the foundations of your project.
Remove some files to have the following hierarchy:
βββnode_modules # External modules required
β βββ{...}
βββpublic # Static files - https://create-react-app.dev/docs/using-the-public-folder/
β βββindex.html
β βββrobots.txt # Prevent crawl up - https://www.geeksforgeeks.org/robots-txt-file/
βββsrc # The folder where you will code
β βββApp.tsx
β βββindex.tsx
βββ.gitignore # Tells git to ignore some files
βββpackage-lock.json # Dependencies manager
βββpackage.json # Package manager
βββREADME.md # Don't hesitate to read it! It contains useful commands
βββtsconfig.json # TypeScript configuration file
It's ok if some errors appear, it will be fixed π
Then follow these steps to setup your project with Chakra UI, a component library to help you build your React projects, ESlint and Prettier.
It will also give you a good architecture to start this day π₯
As always, install the necessary dependencies:
npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
- Update
src/index.tsx
to wrap your app with a ChakraProvider, allowing us to customize behavior around the whole app:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ChakraProvider } from '@chakra-ui/react';
import App from './app/App';
import theme from './theme';
import './theme/index.css';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<ChakraProvider theme={theme} resetCSS>
<App />
</ChakraProvider>
</React.StrictMode>,
);
You can take a look at the Chakra UI tutorial to setup
create-react-app
projects.
Now let's create a custom Chakra theme to extend it with our own preferences π±:
- Create the folder
src/theme
with anindex.css
file inside. Then you can fill it with the following content to use different fonts and add some global CSS:
/* Import fonts from google fonts */
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap');
body {
font-family: 'Poppins' !important;
}
html {
scroll-behavior: smooth;
}
- Add and
index.ts
file in thetheme
folder to define Chakra breakpoints that will help us make it responsive:
import { extendTheme } from '@chakra-ui/react';
// Set breakpoint to help to make the app responsive.
const breakpoints = {
xs: '320px',
sm: '576px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1440px',
};
export default extendTheme({ breakpoints });
To finish the Chakra setup, let's import and use basic components from Chakra
-
Create the folder
src/app
. -
Move the file
src/App.tsx
in theapp
folder and fill it with this to see the power of Chakra in action π₯:
import { Center, Spinner, Text, VStack } from '@chakra-ui/react';
const App = (): JSX.Element => (
<Center mt="160px">
<VStack spacing="32px">
<Text>It's time for you to start frontend development!</Text>
<Spinner w="132px" h="132px" />
</VStack>
</Center>
);
export default App;
Lastly, add "baseUrl": "src"
under the compilerOptions
of your tsconfig.json
.
Check the tsconfig documentation about
baseUrl
to see why it's useful π
You can't install ESLint exactly like the other days, we need to use different configurations to support the React syntax and use ESLint at his full potential π
Install the dependencies:
npm install -D eslint eslint-config-airbnb eslint-config-airbnb-typescript eslint-config-prettier eslint-plugin-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser
What's next? Creating a config file like .eslintrc.yaml
π
Here's a good config to get started:
parser: "@typescript-eslint/parser"
parserOptions:
ecmaVersion: latest
project: tsconfig.json
env:
node: true
browser: true
extends:
- airbnb-typescript
- airbnb/hooks
- plugin:@typescript-eslint/recommended
- plugin:prettier/recommended
- react-app
rules:
prettier/prettier: warn
no-console: off
Don't forget to add scripts to
package.json
:{ "lint": "eslint src", "lint:fix": "eslint src --fix" }
Install the dev dependency:
npm install -D prettier
And define rules like these in a .prettierrc
file:
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2,
"useTabs": true,
"bracketSpacing": true,
"parser": "typescript"
}
To test that everything went well, run the following commands:
# Run lint
npm run lint
# Start the server
npm start
You can continue if they all succeed!
Now that the foundations are laid for your project, it's time to dive into frontend development π
Before going further, be aware of this:
As you are using Chakra UI, you mustn't use HTML tags. In fact, Chakra makes available plenty of components, such as Button
, Box
, Flex
, Stack
... You can find the full list here.
It's important to take time to read this list, it will save you a lot of time for the rest of the day π
For all the following steps, you will have three sections:
- Requirements: what you must have
- Constraints: what you must follow
- Tips: what you must read and use
Let's start by creating the Home page π
Requirements:
- The Home page must contain:
- a title
Artists Book
- a subtitle
Manage your favorite artists
- a title
Constraints:
- Create the file
src/pages/Home.tsx
with a React Component representing your Home page inside. - Update the file
src/app/App.tsx
to call this component.
Make sure you understood everything from the foundations.
Have a look at the Chakra UI Text and
Heading
components π
Well done! You have created your first React Component π₯³
π‘ A great idea is to create a folder
src/components
to store reusable components.
From now on, you are free to add any element you want in your UI as long as you have the requirements. Chakra UI is a really powerful tool, have fun with it π₯
Don't hesitate to ask us questions about design, about ways to code frontend elements, or to validate your architecture π
Here is an example of what you will have to do
Note that this is purely frontend, there is no interaction with a database.
Now that you have your Home page, it's time to have Register and Login pages reachable at the /register
and /login
URLs.
Requirements:
- The Home page must contain:
- A
link
to the Register page. - A
link
to the Login page.
- A
- The Register page must contain:
- An
input
to enter anemail
. - An
input
to enter apassword
. - An
input
to enter theconfirmed password
.π‘ Text for the password inputs mut be replace by dots
- A
button
that when clicked, log the values of the email, the password and the confirmed password. - A
link
to the Login page.
- An
- The Login page must contain:
- An
input
to enter anemail
. - An
input
to enter apassword
with text replaced by dots again. - A
button
that when clicked, log the values of the email and the password. - A
link
to the Register page.
- An
Constraints:
- You must create the file
src/pages/Register.tsx
. - You must create the file
src/pages/Login.tsx
. - You must create the file
src/app/Routes.tsx
with a React Component containing the Routes inside, called insrc/app/App.tsx
.
Tips:
- Have a look at the Chakra UI Input, Link and Button components.
- You should have a look at the react-router-dom package.
- Check the React State Hook π
- Use the web console to see the logs (Ctrl + Shift + I) π
Now that you have several pages, its time to make sure that they are responsive on different screen sizes π
To do so, open the console and play with the screen width and height (CTRL + SHIFT + M while inside the console π)
If some elements are not responsive, fix it!
Requirements:
- Check:
- The arrangement of the elements.
- The spaces between elements.
- The text size (especially for titles and subtitles)
- ...
Tips:
- Here is how to do with Chakra UI. As you can see, the setup has already been done!
Great, you now have a good looking responsive UI, but how do you make sure it works well without manually testing?
A great tool for front-end testing is Cypress, mainly used for end-to-end and component tests.
To win time, we already created some tests for you, you'll just need to adapt them to your application π
First, let's install the necessary dependencies:
npm i -D cypress @types/jest
Then you have to add the necessary scripts in the package.json
:
"cypress:run": "cypress run",
"cypress:open": "cypress open",
You can run the tests directly in the CLI or open an UI to do so π
Once this is done, extract the given files. You should have a cypress
folder at the root of your project with the test files located in cypress/e2e
, and a cypress.config.ts
file also at the root.
π‘ You'll notice the
cypress/videos
andcypress/screenshots
folders, when you run the tests cypress will fill these directories with content to help you debug your tests if they fail. You can add them to your.gitignore
to avoid committing them.
Lastly, you will need to add some id
to the components of your UI. They will be useful to find content of your UI, especially here for the cypress tests.
For example in home.cy.ts
, you have this test for the title where we find the UI content based on the app-title
id:
it('Good title', () => {
cy.get('#app-title').should('contain', 'Artists Book');
});
When you're done, you can use npm run cypress:run
and admire the passing tests π
During the next steps, feel free to add tests for the new components and pages you create π
Now that you have solid foundations, it's time to go further π₯
You have a Home page, a Register page and a Login page. What's missing? A Dashboard page!
Let's now play with artists π
π‘ To see what is an
Artist
, check the API doc
Create a Dashboard page listing some artists, with the /dashboard
URL.
β οΈ For now, data is stored with a ReactuseState
hook. There is no real database and no interaction with the API.
Requirements:
- Update the Register
button
to redirect to the Dashboard page when clicked. - Update the Login
button
to redirect to the Dashboard page when clicked. - The Dashboard page must contains:
- A
navbar
in the top with:- A
link
to the Dashboard page on the left. - A
button
Add an Artist
on the right, doing nothing for now.
- A
- A
grid
listing artists'scard
.
- A
Constraints:
- You must create the file
src/types/artist.ts
with theArtist
type inside. Be smart, take only the needed properties π - You must create the file
src/pages/Dashboard.tsx
. - You must create the file
src/components/Bar/TopBar.tsx
with the topnavbar
inside. - You must create the file
src/components/Button/AddArtistButton.tsx
with theAdd an Artist
button
inside. - You must create the file
src/components/Card/ArtistCard.tsx
with the artists'scard
inside, displaying every information about an artist except from hisid
.Try to display the
rating
using 5 stars β
Tips:
β οΈ Be careful with the Chakra UI templates, it's just to give you an idea of what you can do. Do not copy-paste code.
Now that you can list artists, what if you could add some?
As you can notice, your Add an artist
button does nothing for now.
Let's add artists in a cool way π: when this button is clicked, a modal
appears with a form to create an artist.
Constraints:
- You must create the file
src/components/Modal/AddArtistModal.tsx
with themodal
to add an artist inside, called insrc/components/Button/AddArtistButton.tsx
.
Tips:
- Chakra UI has a component perfectly fit for this use case: the Modal π₯
First, well done! You've worked hard to be here π
It's time to give you a gift: an advice π
One of the most difficult thing when you build a User Interface with React (and other libraries of components / frameworks) is to manage the dozens of components you create.
But why is it difficult?
It's because your components are not stateless. There is logic inside them. For instance, sometimes you will copy-paste a whole component, just to change a condition, a function...
It's really difficult to build components that you can re-use in different parts of your project.
So how can you resolve this problem?
One of the best thing to do is to build stateless components.
Keep your logic, your function calling APIs... the higher in your tree component. Pass functions, conditions... as parameters to your components.
It might not seem important right now, but it will help you so much.
To set this up, here is a little challenge you can take: all your logic, keep it inside the pages components, and only there.
If you want to go further in frontend development, follow this principle as much as you can π
Now that you have built your User Interface, it's time to call the API and interact with real data π
Please take a moment to setup this.
Feel free to play with it with a tool like Postman.
Let's call the API when a user registers π§ββοΈ
Requirements:
- The user must be notified with the appropriate message if the register action succeeds or fails.
- The Register button cannot be clickable if the credentials are invalid.
- On success, redirect the user to the Dashboard page.
Constraints :
- You must have an env variable
REACT_APP_BACKEND_URL
. - You must get the
REACT_APP_BACKEND_URL
inside the filesrc/config/services.ts
, and only here. - You must create the folder
src/services
and keep the functions calling the API inside it. In your React components, you will call these functions. Be smart, you're free to organize this folder as you want.
Tips:
- Have a look at the axios and env-var packages.
- Another step, another Chakra UI component! This time, look at the toast component.
- Take a look at the localStorage, this is where you can keep the
accessToken
.
You will store the given accessToken
inside the localStorage
.
Note that this is a bad idea.
Please refer to the Security Bonus to understand why.
We ask you to do it this way because it's important to be aware of this.
Now that you know how to call an API from a User Interface, it's time to have a complete interaction with it!
Requirements:
- On successful login, redirect to the Dashboard page.
- The user must be notified with the appropriate message on login.
- The user must be authenticated on the Dashboard page. If not, redirect him to the Home page.
- The user must be notified with the appropriate message on artist creation.
Constraints :
- Follow the previous constraints and structure your code π
Tips:
- You already have all you need, but you can ask the staff if you struggle π
Well, we have artists. What about musics?
Create an Artist page listing all of his musics.
Requirements:
- When an artist is created, redirect the user to this artist's page.
- The Artist page must contains:
- The same top
navbar
as the Dashboard page. - The photo / name / rating / nationality / music gender of the artist, displayed in a nice way.
- An
Add a music
button
opening amodal
to add a music when clicked. - A
grid
listing his music'scard
.
- The same top
Constraints:
- You must create the file
src/components/Card/MusicCard.tsx
with the musics'scard
inside, displaying every information about a music except from itsid
. - You must create the file
src/components/Button/AddMusicButton.tsx
with theAdd a Music
button
inside. - You must create the file
src/components/Modal/AddMusicModal.tsx
with themodal
to add a music inside, called insrc/components/Button/AddMusicButton.tsx
.
Tips:
- This is not the time to optimize your number of requests to the API. Keep it logical.
Congratulations for completing this day, you're now able to create a beautiful frontend for your own project π€©
Here are some bonuses for you if you still have time:
Improve your User Interface using animations π₯
Here are the best two libraries:
We advice you to use Motion as it is already installed with Chakra UI π
Implement a Dark and Light Mode thanks to Chakra UI πΆοΈ
As stated earlier, storing a JWT inside the localStorage
is a bad idea. Here is how to solve this problem π
Your turn!
What if you could share data between different components without passing parameters to them?
Well it's possible, it's called React Context.
Try to use it.
π Don't hesitate to follow us on our different networks, and put a star π on
PoC's
repositories.