Presentation


Intro

Hi all! According to tradition, I will say few words about myself. So:

  • Six years in the industry.
  • Have production experience working with all the top-3 UI frameworks: Angular, React and Vue.

So, the mail question: Who is this presentation for?

I see as my target audience of:

  • developers who have experience working with any other frameworks (not React)
  • or those developers who are in search of their first framework

Today’s presentation will help you understand what’s going on in the world of React.

This will be a general overview of the framework, it will help you get acquainted in its capabilities


Reconsilation

DOM manipulation a lot slower than most JavaAScript operations. This is well-known fact.

Therefore, all frameworks strive to optimize work with DOM; minimize the number of redraws; combine several changes into one call; and also find the very minimal part that needs to be redrawn;

Virtual DOM like a light copy of the DOM, where every node is a JS object.

  • Every time something changes, a new virtual DOM is created.
  • The difference between the new and the old virtual DOM is calculated.
  • The real DOM is patched with that difference.

On ReactJS virtual DOM implementation, every node is an immutable instance of a JS class called ReactElement. Their immutability makes them easier to be compared.

What happens when there is a change on a component?

  • A listener gets notified about it, and triggers an update process
  • A new virtual DOM is generated.
  • A reconciliation is done through diffing algorithms. This step is executed to know exactly what is different between the new and the old virtual DOM.
  • The original DOM is patched.

The red nodes are the ones that change in the new virtual DOM. The reconciliation process should catch those and treat them as affected nodes.

React team rewrited the reconciliation algorithm for v16, and the new algorithm is called Fiber. It uses Scheduling for works.

Scheduling - a planning process that determines when work should be completed

Work - any calculations that must be performed. Usually work is the result of an update (e.g. calling setState)

Fiber allows:

  • stop work and return to it later
  • prioritize different types of work
  • reuse work done earlier
  • cancel the job if it is no longer needed

Questions

Every time I had to research a new framework for the next project (or just out of interest), I asked myself the same questions. and I believe that after receiving answers to them, you can start your work quite comfortably.

So you see these questions on your screen. I am not a fan of the template "10 things you need to know about X"?, Precisely because there are only eight on my list.

As a developer who is just starting to get acquainted with the framework for creating single-page applications, I want to know:

  • How to get started painlessly without wasting time setting up dependencies, builds, linters... (Of course, when you start an enterprise-level project, you will soon find that the standard settings are not suitable for you, and you need a custom configuration. That's for sure)
  • It so happened that the main building block of most front-end frameworks is the Component. This is such a black box that accepts the initial settings and provides api for work
  • Routing, Global (or application) state and http requests - this is the basis for any single page application.
  • Of course, you should not forget about writing tests.

Environment Setup


Node.js | Code Editor | Web Browser

In order to start working as a web developer, you need to install at least three things on your computer

  • Node.js Hope you heard about it. The number of ready-made packages in the official repository is simply amazing. But be careful, remember the story of the left-pad package
  • Code editor The Visual Studio Code icon is not a call to action. You can choose any editor that you like.
  • and of course - a web browser. Chrome browser is enough for our purposes

So, without stopping on instructions how to install it, and with the belief that you already have all this stuff installed on your computer, we move on


Tools

As I mentioned before, it is important to start getting acquainted with the framework's features as easily and simply as possible. And not waste time setting up the environment. Which tools can help us with this?


Create React App

Easy start will provide us create-react-app. Their motto: "Set up a modern web app by running one command".

Great tool for quick start of React applications. You don't waste time setting up Webpack, Babel and other familiar tools. They are preconfigured and hidden, so you can focus on the code.

Just execute the command npx create-react-app <project-name> in the terminal. After the command is completed, you need to go to the folder with the created project and execute the start script. So, by executing just two commands in the console, you will get a sandbox for experiments.

I added a link to the documentation on the slide.

Maybe you will be interested in creating a typescript version of the project. Just add --template typescript to the end of the first command

For those who want to look under the hood and see all the configuration settings (they are hidden by default), there is a script eject. But, this is a one-way ticket, and you will lose the opportunity to return to the default settings, so I do not advise you to do this at the initial stages. Also, after eject you lose the ability to upgrade to new versions.

I attached a tweet to Dan Abramov on the slide, which seems to hint at it


React Developer Tools

It is also necessary to be able:

  • to debug our application
  • look at the state of it's individual parts

React Developer Tools is a browser DevTools extension. It allows you to inspect the React component hierarchies in the browser Developer Tools. It gives you a big productivity boost when working with React.

Once you have installed the React Developer Tools, you can open the regular browser devtools and you'll find new panels: "Components" and "Profiler".

The Components panel shows you the root React components that were rendered on the page, as well as the subcomponents that they ended up rendering. By selecting one of the components in the tree, you can inspect and edit its current props and state in the panel on the right.

The Profiler panel allows you to record performance information


Component

React components let you break up the user interface into separate pieces. Components are the building blocks of any React app will have many of these.

Usually they are divided into:

  • by way of creating: Functional and Class components
  • by the presence of an internal state: Statefull and Stateless
  • Presentational (how things look) and Container (how things work)

How it works

A React component takes an optional input and returns a React element which is rendered on the screen.

One of the types of properties that a parent component can pass to a child is functions.

By calling these functions, the child component can report changes that have occurred. When called, additional information may be passed using arguments.

For example, when closing a modal window, such a function is called without arguments, but if you remove an item from the list, you must pass its id to the function

Also a component can has an internal state. I will explain this in more detail on the following slides.

To summarize:

  • a component receives from a parent props that can be data and callback functions
  • props are immmutable
  • component calls functions to report changes

Functional vs Class

There are two main types of components in React. Class Components and Functional Components.

The difference is pretty obvious. Class components are ES6 classes and Functional Components are functions.

Before the hooks appeared, the choice was made as follows:

If you need to have the internal state, or use lifecycle methods (I will talk about them on the next slide), then you have chosen the class component.

If you needed to draw a simple component, without the above requirements - you chose a functional component

React hooks was the game-changer, but traditional classification was:

  • Class, Smart, Stateful, Container because they are basically classes, can contain logic, can hold and manage local state, usually they contain other (mostly functional) components

versus

  • Functional, Dummy, Stateless, Presentational because they are basically functions, all they do is output UI elements

JSX

As I mentioned, the component returns a DOM node, and for a more convenient markup in the components, JSX is used

JSX is an XML/HTML-like syntax. The syntax is intended to be used by preprocessors (i.e., transpilers like Babel) to transform HTML-like text found in JavaScript files into standard JavaScript objects that a JavaScript engine will parse.

A browser cannot execute JavaScript files containing JSX code.

React uses JSX for templating instead of regular JavaScript

  • JSX allows us to write HTML elements in JavaScript and place them in the DOM
  • JSX converts HTML tags into react elements.

alternative solution is to use the function React.createElement()

On the left is an example of using JSX, on the right you can see an alternative React.createElement syntax. Honestly, things like Babel turn the left side into the right. My opinion - is that they will do it than me.

To summarize:

  • React components return DOM nodes.
  • Class components do it using the render method, for functional - just return the JSX markup from the function
  • null is used as the return value if we have nothing to show into the DOM

On this slide, we made out what components are returning to us. Now let's see what happens inside.


Props

I already mentioned that the component receives props and may have an internal state. These are the two main concepts in our React dictionary for now.

Props are an optional input, and can be used to send data to the component. They are immutable.

We can use the JavaScript data types as props (number, string, boolean), functions... We can pass another component to it. Or a function that, based on the arguments received, will return one of the components

Props are used to:

  • initially configure the component
  • the component reacts to their change
  • there are also types of properties (functions) that the component will call, giving them new values.

It is important that properties of the correct types are passed to the component. And where we expect to see the string, suddenly the object did not appear.

Yes, this can be controlled with the help of a typescript or flow, but is there any way "out of the box"?

There is a separate package for these purposes, prop-types. Once it was part of the React, but then it was separated. Pay attention to property Modal.propTypes. This is an example of the description of expected types for the passed props.

isRequired are those props without which the life of the component is impossible.

To assign default values for optional props, you can use ```Modal.defaultProps``, or append default values directly to function arguments (for functional components). Thank you for this EcmaScript 6.


Children Prop

Separately, I want to give you an example of a special property, called children. This is such an implementation of the default slot in the React.

Anything that falls between the opening and closing tag of a component can be inserted inside its markup using this property.

Speaking specifically about this example. We have many places in the application where it is necessary to display the user card. But the actions that we will carry out are different everywhere, so here we pass a few buttons to the markup "Call" and "Message". Elsewhere there may be a "Delete" button. Or "Add to favorites"


Handle events

Everything is simple, as seen on the screen. Some rules:

  1. Use camelCase
  2. In class components, watch for this. It's easy to lose. bind and class properties - these are our best helpers
  3. You can pass the function in brackets without calling (like handleDelete example) or wrap it if you need to add additional arguments to its call on the fly

FYI: React uses a SynteticEvent wrapper, but almost everything looks as usual, including e.preventDefault and e.stopPropagation


State

State is the way of storing local data in React.

The key difference between props and state is that the state is private and can be changed from the component itself.

Props are external, and not controlled by the component itself. It’s passed down from components higher up the hierarchy.

A component can change its internal state directly. It can not change its props directly.


Before the appearance of hooks, which I have already mentioned several times, only class components could have an internal state.

Now everything has changed, and I'll give you two examples here, how to use the state for class and functional components.

Step 1: The state must be initialized, you must assign it an initial value. For class components, this can be done as this.state = equal, for functional component - here is this line of code using a hook useState.

Step 2: You can then use the current state in the markup, referring to it like this.state.isModalOpen and without this for functional component.

Step 3: In order to change state, for class components you must use this.setState. There may be two forms of using. In the first, we simply pass the object with the changed values (when the state does not depend on the previous one). And the second option - you must pass a function that, when called, will receive the previous state, and will be able to use its values to return the next state. We need prevState because state updates are asynchronous. Also, React is trying to optimize (minimize) the number of state changes, because it is a slow redraw. Therefore, if your next state depends on the previous one, use the function call

For functional components a little easier - just pass a new value to the function call, that we received after the destructuring (setIsModalOpen) in our case.

To summarize:

  • State is now available for functional & class components
  • it is used to save values between redraws
  • status update - asynchronous action

Lifecycle for class components

You can think of React *lifecycle methods8 as the series of events that happen from the birth of a React component to its death.

Every component in React goes through a lifecycle of events. there are three different phases:

  • Mounting

    • render method is the most used lifecycle method (the only required). It happens during the mounting and updating of your component. It has to be pure with no side-effects.
    • componentDidMount is called as soon as the component is mounted and ready. This is a good place to initiate API calls, add event listeners
  • Update

    • componentDidUpdate is invoked as soon as the updating happens. The most common use case for the componentDidUpdate() method is updating the DOM in response to prop or state changes.
  • Unmount

    • componentWillUnmount is called just before the component is unmounted and destroyed. If there are any cleanup actions that you would need to do, this would be the right spot. If you added listeners with componentDidMount, it's time to delete them to avoid memory leaks and unexpected behavior

Fragment

So, there is no way to return multiple elements from a component, there should always be a component-wrapper And in most cases this works fine. But what if you still need to do this? Typically, these components are wrapped in a tag, for example div.

Here is where React Fragments come in. React Fragments can group a list of children without adding extra nodes to the DOM. This is a much need addition in React, because you can just use React Fragments, which don’t render in the DOM, instead of using real elements like div.

To summarize:

  • Fragments are invisible and do not get added on to the DOM.
  • Fragments can take in keys as an attribute.

Hooks

Hooks were introduced in React version 16.8. Hooks solves the problem of code reuse across components. They provide you a way to split a component, into smaller functions.


What is it trying to solve

‘Hooks are functions that let you “hook into” React state and lifecycle features from function component. They do not work within a class. They let you use React without a class.’ – React Official Blog post.

The main reasons behind introducing Hooks, is the readability and simplicity aspects of code.

With simple and pure functional components, now the code is a lot easier to read and understand.

With classes, the code could get complex for some components.

NOTE: Hooks don’t work inside classes (because they let you use React without classes).


Example

I'll show you an example. This is SuggestionList component.

Here I use the three most common - useState, useEffect, useRef;

This is a complete example, now let's dive into the implementation details


useState

The purpose of the useState hook is to add state to your functional components in React, without having to use a class.

  1. The first thing we need to do is import the useState from React.
  2. The second step is to declare the state variable for the component

It returns a pair of values: the current state and a function that updates it.

In our example, selectedOption can be used in render, setselectedOption is going to behave the same as setState from class components

Thus, the problem of storing the internal state for functional components is solved


useEffect

useEffect hook allows side effects within the functional component. In class components, we can use lifecycle methods.

The most popular lifecycle methods: componentDidMount, componentDidUpdate and componentWillUnmount, are all handled by the useEffect hook in functional components.

useEffect hook takes 2 arguments. The first is a function. If another function is returned from this function, it will work as componentWillUnmount

Now lets look into the 2nd argument. there are several options:

  1. If it is absent, it will work as componentDidMount + componentDidUpdate - on every component render

  2. If it is an empty array => as componentDidMount - when component mounts

  3. if it is an array with conditions => componentDidMount + componentDidUpdate for conditions only on every component render with a condition

  4. to achieve the effect only componentDidUpdate, you will need to write your custom hook. It is very simple

First useEffect just for focus on select and works as componentDidMount

Second will get items on mount and then, for every searchString change


Custom hooks

I will show you an example of writing a custom hook.

It is intended to perform actions if the click occurred outside the element. This can be useful to close the modal window, or to collapse the list.

Remember, hooks are just functions.


CSS Styles

Now we come to the next big section. How to style components?, because we create UI interfaces!

Everyone knows the main problem of CSS - this is the global scope of styles.

Adding style to one block can unexpectedly get the same in another block


Possible solutions

And now I will show you some possible ways how to style components in a React.

I just want to clarify that the list is far from complete, this is directly the topic for a separate presentation.


Inline CSS

Using the style attribute, you can pass styles to elements. Please do not abuse it.

Move on, this is not an option for good projects


CSS Stylesheet

My opinion is that it can be used for global styles, for common layout elements.

Syntax: just import the css file into the component file, and configure the bundler


CSS Modules

CSS Modules is not an official spec or an implementation in the browser but rather a process in a build step (with Webpack, for example)

During build step, the compiler would search through that styles.module.css file that we’ve imported, then look through the JavaScript we’ve written and make the .title class accessible via styles.title. build step would then process both these things into new, separate HTML and CSS files, with a new string of characters replacing both the HTML class and the CSS selector class.

[the classes] are dynamically generated, unique, and mapped to the correct styles.

This approach is designed to fix the problem of the global scope in CSS.


Preprocessors

Not much different from using a regular CSS, it just has a several additional features.

Here is an example with BEM (Block - element - modifier).

The main thing I wanted to show with this slide is that you can use different file extensions by simply setting up the bundler correctly


CSS in JS

One particularly interesting concept is using JS in CSS to abstract CSS to the component level itself, using JavaScript to describe styles in a declarative and maintainable way. With the release of the popular styled-components project by Max Stoiber, this concept is more mainstream today than ever.

Here you can see screenshots from the emotion website, and two different syntaxes

Below I added a link to the comparative page of different libraries, there are so many of them


Styled components

Styled-components are created by defining components using the ES6 template literal notation. CSS properties can be added to the component as needed, just like you would normally do using CSS. When the JS is parsed, styled-components will generate unique class names, and inject the CSS into the DOM.

The main thing you need to understand about Styled Components is that its name should be taken quite literally. You are no longer styling HTML elements or components based on their class or HTML element. Instead, you’re defining styled components that possesses their own encapsulated styles.


Routing

Routing is the capacity to show different pages to the user. That means the user can move between different parts of an application by entering a URL or clicking on an element.

As you may already know, by default, React comes without routing. And to enable it in your project, you need to add a library named react-router.

React Router conditionally render certain components to display depending on the route being used in the URL


Components

To build a routing, we need four main components: Router (container), Switch, Route (to decalare routes) and Link.

All names are very clear and hint at their responsibilities.


Example

Let's look at an example

We need to wrap everything in a Router wrapper, use the Link to navigate, describe the routes using the Route and add the ability to switch them using Switch


Hooks

Well, and how without hooks?

For more convenient work, by default we get several hooks:

  • for working with history instance
  • for working with location object,
  • as well as access to parameters

On the slide, I gave an example that shows how easy it is to use.


Global State

The main idea is abstracting the application data from the document object model (DOM).


Context API

Context API allows for an easy way to share global data between multiple components without having to pass it as props. It solves a common problem known as the prop-drilling . Where props would need to be passed down to multiple components in the tree to reach the component that needs it.

The Context API is especially useful to provide data that’s needed by a high percentage of the components in the tree. Global preferences like the selected theme or selected locale option are two good examples.

When React version 16.3 came out, articles with headlines began to appear "This is the killer of the Redux", "You Might Not Need Redux".

My opinion - Redux are still needed in applications with a medium or complex structure, and the Context API is more suitable for small component blocks or for use in a large number of components (as a theme);


Example

  1. Create context with default value
  2. Wrap components into Provider
  3. Use theme in component

That's all, we defeated prop-drilling problem


Redux

Redux architecture revolves around a strict unidirectional data flow.

Redux is only responsible for the state and is in no way associated with the browser, DOM and the frontend as a whole. It can be used on its own, even on a backend in Node.js.

Redux is ideal for medium to large applications. It should be used only in cases when it is impossible to control the state of the application using the Context API.

In general, use Redux when you have reasonable amounts of data changing over time, you need a single source of truth, and you find that approaches like keeping everything in a top-level React component's state are no longer sufficient.

Simple Redux applications are not needed.

The fundamental building blocks of Redux are action, reducers, middleware, and the store

  • The Store is the object (holds application state;)
  • Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using store.dispatch().
  • The reducer is a pure function that takes the previous state and an action, and returns the next state. It’s very important that the reducer stays pure

Redux is synchronous!!!


Example

This is an example of how to configure and use Redux in an application with screenshots from the official documentation.


Redux dev tools

And this is a screenshot of what the browser extension looks like, allowing you to debug the state of the application


Redux Saga

As any redux developer could tell you, the hardest part of building an app are asynchronous calls — how do you handle network requests, timeouts, and other callbacks without complicating the redux actions and reducers?

Every time an action, a plain object that describes what happened, is sent to the store, a reducer is called and the state is updated immediately.

But in an asynchronous flow, you have to wait for the response first, and then, if there’s no error, update the state. And what if your application has a complex logic/workflow?

Redux use middlewares to solve this problem. A middleware is a piece of code that is executed after an action is dispatched but before reaching the reducer.

Many middlewares can be arranged into a chain of execution to process the action in different ways. However, the middleware has to interpret anything you pass to it, and it must make sure to dispatch a plain object (an action) at the end of the chain.

Redux-saga is a library that aims to make side effects easier and better by working with sagas.

Sagas are a design pattern that comes from the distributed transactions world, where a saga manages processes that need to be executed in a transactional way, keeping the state of the execution and compensating failed processes.

In the context of Redux, a saga is implemented as a middleware (we can’t use a reducer because this must be a pure function) to coordinate and trigger asynchronous actions (side-effects).


Redux Saga

Redux-saga does this with the help of ES6 generators. By working with Effects, redux-saga makes sagas declarative.

...

If you want an alternative solution - look at the MOBX


HTTP requests

You can use any library you want. Most popular is Axios

All that is needed from such packages is the ability to use interceptors, cancel requests, handle errors - all this is with Axios

I always wrap the axios into a wrapper so that it is easier to replace it with something else in the future


Error Boundaries

Error Boundaries were introduced in React v16 as a way to catch tricky errors that occur during the render phase.

In the past this would have caused the app to unmount completely, and the user would just see a blank web page.

It’s not a new component or JavaScript library. It’s more like a strategy for handling errors in React components.

  • static getDerivedStateFromError is a lifecycle method that allows the Error Boundary a chance to update the state and thus triggering a last render().
  • componentDidCatch is a lifecycle method designed for triggering side-effects (logging, send error)

Instead of completed crashing, we can use Error Boundaries to substitute a fallback UI. This provides visual feedback to the user that something broke, while allowing them to continue interacting with our app.

They can choose to navigate away, or even reach out to customer service to help resolve their situation! It’s a great way to redeem an otherwise unfortunate user experience.


Tests


Enzyme vs testing library

React-testing-library Created by Kent C. Dodds and maintained by a huge community of developers, this library enables you to test components without touching their internal business — which in turn empowers you to conduct more powerful test cases while keeping the user experience top of mind.

However, you cannot:

  • Conduct shallow rendering
  • Access internal business of your components, such as states

Enzyme is a JavaScript testing utility framework designed to help developers test React components easily. It’s maintained by Airbnb and is among the most-used frameworks.

Enzyme enables you to:

  • Use shallow rendering
  • Access business implementations of your components
  • Conduct full DOM rendering
  • Use react-hooks in shallow rendering, with some limitations

Also, I want to recommend you see the presentation of my good friend, Vladimir Pantasenko: "Testing React Applications: Why and How"


Cypress

Cypress enables you to write your tests without any additional testing framework. It has a nice API to interact with page components, and it supports Chrome/Chromium, Canary, and Electron.

What you can do;

Time travel Screenshots and videos Automatic waiting Control network traffic without touching your server to test edge cases


here I am a hello list of links to interesting packages and even one site with examples of custom hooks


End

Well, thanks for your patience, this is the end. If you still have questions, a link to my email is on the first slide