This repository serves as an online course for learning React. It’s here to help those who want to learn more about React and frontend in order to develop a SPA.
At STRV, we believe that the best way of learning is by working on a real project. So, we’ve come up with a simple e-commerce app concept using the Commerce Layer API.
Please take note that by learning React, you will not become a frontend developer. There are many other areas you should be able to handle. Stay tuned for
Frontend Nights
, where we are going to focus on everything except React. :)
The goal of this course is to give you a fundamental understanding of how to build a production-ready React web app.
The presenters demonstrated the best practices in building React applications — experience they gained by working on numerous projects.
This online course was created by utilizing material from React Nights, the free offline course with a focus on React created by STRV.
This course requires at least junior-level knowledge of programming, and relies on fundamental knowledge of React. Reading and understanding this amazing official documentation should be enough to get you started.
General frontend knowledge is beneficial, but not necessary. For more details, you can check the video and presentation from the first lecture
- Introduction
- Course Structure
- Lectures
- Used technologies
- Credits
React Nights 2019 encompasses 8 weeks of studying, 16 lectures and 8 homework assignments. The STRV Frontend Team contributed to this repository throughout the entire course.
STRV also had a dedicated team of mentors helping our students do all of the homework. The team then reviewed the homework as well, of course. :)
We are highly opinionated when it comes to development. There are many great approaches to writing apps; this repository shows you a process that is very close to what we do in the real world.
Our goal was to reveal some patterns incrementally. Some of the code was written in a way that required it to be refactored later. Therefore please don’t think of this repository as a recipe on how to build a React app. It’s more of a showcase of different topics all compiled into a single project.
Each lecture is about 1 hour long. There are 2 lectures per week, followed by 1 homework assignment. You can follow commit history to see each lesson.
You can find recordings of all lectures, as well as links to every presentation, a Pull Request representing the introduction to the lecture, a link to the homework solutions and, finally, some additional resources (also listed in the presentations).
Introduction to the React Nights course. Please note that the course was designed to require a lot of self-studying during homework assignments. If you are planning to take this 16-hours course, we highly recommend you find a mentor who will review your Pull Requests.
Of course, you don't need to wait the entire week before continuing on to the next lesson. But we do recommend dedicating some extra time to studying the shared resources.
If you have any recommendations regarding improvements to this knowledge base, feel free to submit a PR.
As a project starter, we choose create-react-app. (Other great options could be Next.js or Gatsby.) Effective learning requires high-quality code, so we implement Prettier
and ESLint
and enforce it with a pre-commit hook
from a combination of husky
with lint-staged
. And of course, as STRV developers, we use STRV's favorite configurations from code-quality-tools.
Note that we are not covering
stylelint
in this lesson, since it's a part of next week’s lesson - Styling in React. Another decision that should be made from the very beginning isTypeScript from Week 7. But to make the learning curve a bit easier, we decided to add that later. If you are brave enough, feel free to start using it right away.
Before we start to implement features, let’s get the API communication ready. And before any implementation, you should get familiar with whichever API you are going to use.
For our demo, we choose CommerceLayer API. We first read its API Reference and see we need to implement authentication to be able to get any resources. To do that, we need to create an account in CommerceLayer and get a token from API.
For a demonstration of correct implementation, we fetch List of Products
.
That’s all for now. Let's write a simple README about what we did, and how this project can be used.
This homework assignment was implemented during the lecture; see its Pull Request above.
- Set up commercelayer.io
- Project Setup
- Project starter
- API & config
- Fetch list of products
- Code quality tools
- Documentation
- Read Main Concepts in amazing React docs
The plan for this lecture is to implement Product Detail
. For routing, we use react-router. But before we start writing code, let's think about how we will structure the whole project. At STRV, we are fans of grouping by features or routes. This kind of decision should have already been made in lecture 01. Project Setup. So now, we need to refactor our code a little bit.
We will use another API endpoint, so now’s probably a good time to implement a simple http API client
. We will use native fetch for simplicity, but otherwise we highly recommend ky (tiny & elegant HTTP client based on window.fetch
) or rest-hooks.
Now everything is set and ready. Let's go for the Product Detail
!
We have a List of Products and Product Detail. Before we move further, let's implement some decent styles, so that the app is more pleasant to work with.
At STRV, we are big fans of CSS-in-JS - namely styled-components
. A brief introduction to history, benefits, and usage of styled-components. A showcase of styled-system
and @rebass/grid
We also set up the first styleguide. Styles live in the styled.js
file, next to the component. The only exception are global styles and variables files.
With CSS comes huge responsibility. A friendly check put into pre-commit hook by stylelint
is what you need.
And when building a real project, you should definitely check out the Storybook.
- Set up React Router
- Think about and implement the rest of the project architecture
- Fetch and display Product Detail
- Add styles for Product Detail
- https://hackernoon.com/the-100-correct-way-to-structure-a-react-app-or-why-theres-no-such-thing-3ede534ef1ed
- Go through the React Router documentation, especially https://reacttraining.com/react-router/web/guides/philosophy and https://reacttraining.com/react-router/web/guides/basic-components
- The magic behind styled-components: https://mxstbr.blog/2016/11/styled-components-magic-explained/
- styled-components API docs: https://www.styled-components.com/docs/api
- styled-system API: https://github.com/styled-system/styled-system
- https://csstools.github.io/sanitize.css/
- https://www.smashingmagazine.com/2017/01/styled-components-enforcing-best-practices-component-based-systems/
Now is a great time to implement Cart
, as well as the possibility to add products to it. We choose to demonstrate this functionality with Redux, which is one of the most widespread libraries in the React ecosystem. In this lesson, we start with gaining an understanding regarding the state management problem, we explore a number of concepts crucial for implementing the robust state management solution, and we get to build it into our project using Redux best practices.
Redux comes with great middlewares. Let's briefly check what it’s all about. We will leverage this knowledge in the 10. Async Effects & Error Reporting lecture.
Besides that, it's also our duty to showcase a Context API
, which is more than suitable for many use cases. But without any contribution to the project.
Add to Cart
feature on Product Detail pageRemove from Cart
feature on Cart page- Implement redux-devtools and use it with extension
- Extract
Button
component to make it reusable - Add
Layout
to Product Detail page - Update API for getting a list and a single product to return response in the same format
onAddToCart
function expects only productId as an argument. Callingevent.preventDefault()
is done internally now to avoid leaking implementation details to outside components- Remove pseudo-caching logic in ProductList component
- https://overreacted.io/writing-resilient-components/#principle-4-keep-the-local-state-isolated
-
Immutability examples
const user = { id: 1, firstName: 'John', lastName: 'Doe', }
user.age = 30 // wrong const newUser = { ...user, age: 30 } // right
delete user.age // wrong const { age, ...newUser } = user // right
user.firstName = 'Jane' // wrong const newUser = { ...user, firstName: 'Jane' } // right
const users = []
users.push(user) // wrong const newUsers = [...users, user] // right
const users.pop() // wrong const newUsers = users.filter(u => u.id !== user.id) // right
users[0].firstName = 'Jane' // wrong const newUsers = users.map(u => { if (u.id === user.id) { return { ...user, firstName: 'Jane', } } return u }) // right
Proper e-commerce should have a user profile, where our users can change their information or see their past orders. Let's implement a Sign Up
page with Formik and do a client-side validation with yup
Sign in, authentication, private routes, redirecting. With this lesson, our app is almost ready.
- Create the login page with a
login form
- Connect login form to API
- Get customer information and store it in Redux
- Determine in
PrivateRoute
whether a user is authenticated - Show/hide
MyProfile
link according to the authenticated state - Add
log out
functionality
- JSON Web Tokens vs Session Cookies
- Where to Store Your Tokens
- Security
- What are Refresh Tokens
- JWT Open Standard
Our app is almost ready. Now is the time to properly tune it! Of course, in the real world, we should start following "advanced" patterns right away. But for learning purposes, we believe that this is the easiest way how to understand it.
React is functional, so let's learn how to make our app functional as well. This is more of a theoretical lecture, with great examples in the Observable notebook.
During the previous lesson, we saw many code repetitions. Let's make it more DRY!
In this lesson we are doing a minor refactor from redux to hooks. On first sight, it looks good and awesome, but it will backfire us in ### Week 7. This was done on purpose; it allows us to demonstrate that every decision in your codebase matters and requires a lot of thinking.
We’ve now done a major refactor to display how Hooks can save us a lot of typing.
- Product List and Product Detail have been moved to a different route, and root route redirects to Product List
- Route paths have been moved in constants into separate file
src/routes.js
- New route for 404 error was added; it will be shown in case none of the other routes are matched:
Line 38 in 320178f
So far we were following a happy path of development, meaning that everything should be working as expected. But in the real world, that’s never the case. From time to time, the API server is down, internet connection is weak or there is an unexpected error in our code.
Testing is very important in the development of any software. Let's take a look at how it works in the React world. Pull Request comes with a lot of practical examples.
- Move logic to chosen async solution (default: redux-thunks, advanced: redux-sagas, redux-observables)
- Handle refresh tokens
- Notify a user about errors from
server/network
andsuccess
(product added to cart/deleted from cart/logged in) - To mock server responses
401/500
you can use https://www.charlesproxy.com/ - If you find this homework too easy, please refer to
Up for the challenge?
slide for problem inspiration
TypeScript is really trendy these days. We love it at STRV. Hopefully, you will love it too!
In this lesson, we start with the basics of static typing and move on to more advanced topics, such as derived types and type guards. The aim is to bring the power of TypeScript into our application and see how we can type components, reducers and API calls.
Since we are going to production soon, let's think about how our app should work there.Since we are going to production soon, let's think about how our app should work once it’s live.
Because of widely dynamic content, it does make sense to do a SSR. We choose Next.js.
This introduces a major refactor. We could probably choose
razzle
, which has a react-router under the hood. But still, it usually makes sense to make this kind of decision at the very beginning of the project.
- TypeScript
- Move from create-react-app to Next.js
- This is a huge refactor.
- It refers to proper project setup. Meaning you should know what you are building from the very beginning; otherwise, you can choose incorrectly and then spend extra time with an unneeded refactor.
- Convert your codebase into SSR using STRV branch as reference
- Remove
react-scripts
- Add
next
and related libraries (@zeit/next-css
,@zeit/next-typescript
,express
,isomorphic-fetch
,next-redux-wrapper
,@types/next
) - Adjusts scripts section of your
package.json
to work with next instead ofreact-scripts
, check the one defined in the project for reference. - Replace
useApi
hook usage on Products List and Products Details withgetInitialProps
, you could either set the data in redux or show it right away as the hook did. - If you’re feeling like a ninja, implement the loading status in case you decide to go with the redux approach.
Our app seems to be working fine. Let's talk about optimization and bringing users the best user experience possible.
Finally, it's time to deploy our production-ready app!
Again: in the real world, (continuous) deployment could be set up in earlier stages of a project’s lifetime.
Optimize and deploy!
- Project Starters
- create-react-app
- next.js
- Code Quality Tools
- Formatting - EditorConfig, Prettier
- Linting - ESLint, stylelint
- Static Type Checking - TypeScript
- Enforced with pre-commit and pre-push hooks from husky in combination with lint-staged
- React
- Styling
- styled-components
- styled-system
- State Management
- redux
- redux-thunk
- Forms
- Formik
- yup
- Tests
- Jest
- react-testing-library
- Cypress
- 00. Introduction - Danny Kijkov
- 01. Project Setup - Danny Kijkov
- 02. Project Architecture & React Router - Pavel Prichodko
- 03. Styling in React - Nic Reichert
- 04. Global State Management - Konstantin Lebedev
- 05. Context API & Redux Middlewares - Jan Bartos
- 06. Forms - Pedro Ferreira
- 07. Authentication & Routing in Depth - Pavel Prichodko
- 08. Functional Programming - Peter Varhoľák
- 09. HOCs, Render Props, Hooks - Arnost Pleskot
- 10. Async Effects & Error Reporting - Erik Majláth
- 11. Testing in React - Michal Jarnot
- 12. TypeScript - Konstantin Lebedev
- 13. Server-side Rendering vs. Static Export - Luis Felipe Roman
- 14. Optimizing React Apps - Luis Felipe Roman
- 15. Deployment - Soo Jae Hwang
Big kudos to the whole Open Source community for making it possible to create this type of course! ❤️
Of course, thanks to the STRV Frontend Team for participating in the course and helping with the preparation. And finally a huge thanks to our brave students, who took the course and provided us with feedback!