React JS
Agenda
- What does a browser do
- About React
- React Basics
- JSX
- Virtual DOM
- Components
- React Details
React details
- Styling
- HOC & Fragments
- Props & PropTypes
- State
- Routing
- Lifecycle methods
- Refs
- Error Boundary
What does a browser do?
The main function of a browser is to present the web resource you choose, by requesting it from the server and displaying it in the browser window.
Rendering engine
initial
Painting the render tree
Layout of the render tree
Render tree construction
Parsing HTML to construct the DOM tree
Reflow
RePAint
When the changes affect document contents or structure, or element position, a reflow happens.
- DOM manipulation;
- Contents changes, including text changes in form fields;
- Calculation or altering of CSS properties;
- Adding or removing style sheets;
- Changing the "class" attribute;
- Browser window manipulation;
- Pseudo-class activation (:hover).
When changing element styles which don't affect the element's position on a page (such as background-color, border-color, visibility), the browser just repaints the element again with the new styles applied (that means a "repaint" or "restyle" is happening).
React
- Created in March 2013 By Facebook Team (v 16.8.3)
- 2 131 256 downloads last week at NPM (2018)
- 6 119 017 downloads last week at NPM (2019)
- 123583 stars at Github
A JavaScript library for building user interfaces
ReactJS is only a view layer.
We built React to solve one problem: building large applications with data that changes over time
Main points
- React is a JavaScript library for building user interfaces
- React codebase consists of components, which may be written with the help of JSX or not;
- React uses a concept called Virtual DOM. That selectively renders subtrees of nodes based upon state changes;
- React also presents some useful features to handle events.
Benefits
- Virtual DOM;
- One-direction data flow;
- Reusable components;
- Great Developer Tools;
- Huge and growing ecosystem;
- Easy to learn, easy to use
- Dev Community
REACT basics
"Hello world"
import React from "react";
import ReactDOM from "react-dom";
const element = React.createElement(
"h1",
{className: "title"},
"Hello World!"
);
ReactDOM.render(element, document.getElementById("root"));
Elements are the smallest building blocks of React apps.
ReactDOM.render (nextElement, container, [callback]);
/*
* @param {ReactElement} nextElement element to render.
* @param {DOMElement} container DOM element to render into.
* @param {function} callback function triggered on completion.
*/
React Element is a plain JS object
const element1 = React.createElement (
"h1",
{
id: "id_001",
className: "main_title",
key : "001"
},
"Hello World!"
);
console.log(element1);
{
type: "h1",
props: {
id: "id_001",
className: "main_title",
children: "Hello world"
},
key: "001",
ref: ""
}
const elem1 = React.createElement(
"h1",
{id: "id_001", className: "my_title"},
"Hello World!"
);
const elem2 = React.createElement(
"div",
{id: "id_002", className: "my_desc"},
"Some description..."
);
const root = React.createElement("div", null, elem1, elem2);
ReactDOM.render(root, document.getElementById("container"));
JSX
JSX is a XML-like syntax extension to ECMAScript
const helloWorld = <div> Hello World! </div>;
HelloWorld.jsx
React.createElement("div", null,
React.createElement( "h1", null, "Title"),
React.createElement("div", {className: "child1" },
React.createElement("div", { className: "child1_1" }, "Sometext"),
React.createElement("div", { className: "child1_2" }, "Sometext")
),
React.createElement("div", {className:"child2"},
React.createElement("ul", null,
React.createElement("li", null, "1"),
React.createElement("li", null, "2"),
React.createElement("li", null, "3")
)
)
);
<div>
<h1>Title</h1>
<div class ="child1">
<div class = "child1_1">Some text</div>
<div class = "child1_2">Some text</div>
</div>
<div class = "child2">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</div>
ReactElement tree
HTML
JSX compiles to regular JS (NOT TO HTML), so you don’t need to use it, in case you don’t want to
<div> Hello World! </div>
React.createElement(
"div",
null,
"Hello World!" );
JSX
JS
React's JSX uses the upper vs. lower case convention to distinguish between local component classes and HTML tags
<Hello> Hello World! </Hello>
React.createElement(
"Hello",
null,
"Hello World!" );
JSX
JS
JSX is an EXPRESSION
const getGreeting = user => {
if (user){
return <h1>Hello, Friend</h1>
}
return <h1> Hello, Stranger</h1>
}
JS statements in JSX
<div>{ if (true) return "Hello"}</div>
<div>{true ? "Hello" : null}</div>
<div className = {"myClass"}></div>
<div className = "myClass" ></div>
<div className></div>
React.createElement(
"div",
{className: "myClass"}
);
React.createElement(
"div",
{className: "myClass"}
);
React.createElement(
"div",
{className: true }
);
Booleans, Null, and Undefined Are Ignored
<div/>
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{true}</div>
<div>
{ showHeader && <div>Header</div> }
<div>Content</div>
</div>
KEY
var data = ["item1", "item2", "item3", "item4", "item5"];
var list = <ul> {data.map((elem) => <li>{elem}</li>)} </ul>
ReactDOM.render(list, document.getElementById("container"));
Virtual dom
Virtual DOM is a JavaScript representation of the DOM. React Element is the main building block of Virtual DOM.
The process of updating your UI to match your application state
The Virtual DOM is an abstraction of the HTML DOM. It is lightweight and detached from the browser-specific implementation details. Since the DOM itself was already an abstraction, the virtual DOM is, in fact, an abstraction of an abstraction.
Virtual DOM Process
Components
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.
Components are functions that accept arbitrary inputs (props) and return React elements describing what should appear on the screen
const welcomeMessage = (props) => (<h1>Hello {props.name}</h1>)
class WelcomeMessage extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Functional Component
Class Component
class App extends Component {
constructor() {
super();
this.state = { counter: 0 };
}
render() {
return <div className="container">
<div className="alert alert-success">
{this.state.counter}
</div>
</div>
}
}
Class component
When to use a Class Component over a Function Component?
If the component needs lifecycle methods then use class component otherwise use function component.
React.PureComponent is exactly the same as React.Component except that it handles the shouldComponentUpdate() method.
When props or state changes, PureComponent will do a shallow comparison on both props and state.
Component on the other hand won't compare current props and state to next out of the box. Thus, the component will re-render by default whenever shouldComponentUpdate is called.
Create react app
npm install -g create-react-app
create-react-app my-app
//or
npx create-react-app my-app
cd my-app
npm start
Styling
- Inline styles
- CSS/Sass stylesheets
- CSS Modules
- Styled Components
Inline styles
const divStyle = {
margin: '40px’,
border: '5px solid pink’
};
<div style={divStyle}>
<p style={{color:'#FF5733', backgroundColor: 'black’}}>
Error message
</p>
<p style={{margin: 30}}> Welcome message goes here</p>
</div>
CSS/sass stylesheet
//footer.scss
.FooterMessage {
margin: 40px;
border: 5px dotted red;
border-radius: 5px;
}
//component.jsx
import React from 'react';
import './footer.scss';
let Footer
export default Footer = () =>
<p className='FooterMessage'>This is footer</p>
CSS modules
//footer.module.scss
.content {
font-size: 15px;
text-align: center;
}
//component.jsx
import styles from './footer.module.scss';
const Paragraph = () =>
<p className={styles.content}>
This is a paragraph with CSS module
</p>
export default Paragraph;
styled components
import styled from 'styled-components';
const Button = styled.button`
background: transparent;
`;
const Container = styled.div`
text-align: center;
`
render(
<Container>
<Button> This is styled button</Button>
</Container>
);
High Order components
A higher-order component (HOC) is a function that takes a component and returns a new component.
It's a pattern that is derived from React's compositional nature.
- Code reuse, logic and bootstrap abstraction.
- Render hijacking.
- State abstraction and manipulation.
- Props manipulation.
function withNewTitleHOC(WrappedComponent) {
return class Test extends Component {
render() {
const newProps = {
title: ‘This is New Title’
}
return <WrappedComponent {...this.props} {...newProps} />
}
}
}
Fragments
Assumption:
It’s ok to OK to use divs in large React application
Reality:
Ok, I’ll use it here, and here, and here… Wait a minute where is my component?
- Fragments are a bit faster and use less memory by not creating an extra DOM node. This only has a real benefit on very large and deep trees.
- Some CSS mechanisms like Flexbox and CSS Grid have a special parent-child relationships, and adding divs in the middle makes it hard to keep the desired layout.
- The DOM Inspector is less cluttered.
Why Fragments are better than divs?
Props & State
State
State of a component is an object that holds some information that may change over the lifetime of the component.
We should always try to make our state as simple as possible and minimize the number of stateful components.
State is similar to props, but it is private and fully controlled by the component.
It is not accessible to any component other than the one that owns and sets it.
Stateful Component
- Know how everything works
- Just a container for other components
- Provide application data
- Perform data fetching
Stateless Component
-
Know how to display received data
-
Receive and operate only with props
-
Usually the same as functional components
Parent-child communication
The best ways how to communicate between parents and children is to use state and props, or state management libraries like Redux, MobX etc
Communication with callbacks passed via props from stateful components to their children to mutate state of the parent component
Proptypes
- Nice library to type check your application
- Help with finding issues at early stages ( while development)
- Checks JS types, react elements, many items, required props and so on
- Won’t help in production mode
- Flow or TypeScript provide more features
but
YourComponent.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
reqString: PropTypes.string.isRequired
}
Routing
A single-page application (SPA) is a website that re-renders its content in response to navigation actions (e.g. clicking a link) without making a request to the server to fetch new HTML.
The point of a single-page application is to avoid requests hitting the server (during navigation). It is ok to load a new piece data from server for a new route (via AJAX) BUT we need to avoid to load HTML/CSS/JS content during navigation
How?
REACT ROUTER
npm i react-router-dom
Typically apps will use one of the high-level routers:
- <BrowserRouter>
- <HashRouter>
- <MemoryRouter>
- <NativeRouter>
- <StaticRouter>
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { HashRouter as Router, Route, Link } from 'react-router-dom';
const Home = () => <p>Home</p>;
const About = () => <p>About</p>;
const NotFound = () => <p>404 Not Found</p>;
export class App extends React.Component {
render() {
return (
<Router>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route component={NotFound} /> // 404 page
</Router>
);
}
}
To navigate - use <Link> or <NavLink> componants from react-router-dom
import { NavLink Link } from 'react-router-dom';
<NavLink to="/about"> About </NavLink>
<Link to="/"> Home </Link>
Nested routes
Path prop of <Route>
const App = () => (
<BrowserRouter>
<div>
<Route path="/tacos/:id" component={Tacos} />
</div>
</BrowserRouter>
);
const Tacos = (props) => (
<div>
<Route path={props.match.params.id + "/carnitas"} component={Carnitas} />
</div>
);
<Redirect> component will navigate to a new location
LifecyclE Methods
The component lifecycle has three distinct lifecycle phases:
Unmouting
Updating
Mouting
render( ) is the only required method in a component
The component is ready to mount in the browser DOM.
In this phase, the component get updated in two ways, sending the new props and updating the state.
The component is not needed and get unmounted from the browser DOM.
Mounting
constructor()
only used for two purposes:
- Initializing local state by assigning an object to this.state.
- Binding event handler methods to an instance.
If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.
Avoid introducing any side-effects or subscriptions in the constructor, use componentDidMount() instead.
static getDerivedStateFromProps()
render()
componentDidMount()
getDerivedStateFromProps exists for rare use cases where you need derived state.
Mounting
render()
only required method in a class component. When called, it should examine this.props and this.state and return one of the following types:
- React elements
- Arrays and fragments
- String and numbers
- Booleans or null
render() will not be invoked if shouldComponentUpdate() returns false
Mounting
componentDidMount()
executed after first rendering, immediately after a component is mounted (inserted into the tree).
This method is a good place to make all AJAX requests, DOM or state updates, and set up event listeners and any subscriptions.
If you do that, don’t forget to unsubscribe in componentWillUnmount().
Updating
shouldComponentUpdate()
determines if the component will be updated or not.
By default it returns true.
If you are sure that the component doesn't need to render after state or props are updated, you can return false value.
It is a great place to improve performance as it allows you to prevent a re-render if component receives new prop.
Do not rely on it to “prevent” a rendering, as this can lead to bugs.
Consider using the built-in PureComponent instead of writing shouldComponentUpdate() by hand.
PureComponent performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update.
Updating
getSnapshotBeforeUpdate()
executed right before rendered output is committed to the DOM.
Any value returned by this will be passed into componentDidUpdate().
This is useful to capture information from the DOM, for example scroll position.
Updating
componentDidUpdate()
mostly it is used to update the DOM in response to prop or state changes.
This will not fire if shouldComponentUpdate() returns false.
Legacy Lifecycle Methods
UNSAFE_componentWillMount() executed before rendering and is used for App level configuration in your root component
UNSAFE_componentWillReceiveProps() executed when particular prop updates to trigger state transitions
UNSAFE_componentWillUpdate() executed before re-rendering the component when there are props & state changes confirmed by shouldComponentUpdate() which returns true
REF
Almost the same as getElementById, needed for:
- Managing focus, text selection, or media playback.
- Triggering imperative animations.
- Integrating with third-party DOM libraries.
Special properties allowing to refer to the corresponding instance
Give ability to get access to the DOM node.
React automatically destroy refs (or set null if you use callbacks) if element was destroyed.So don’t worry about memory leaks.
Don’t make sense to use ref for functional components because they have no instances.
Allow get access to the child component instance using refs. Method also can be called but it’s not recommended.
ERROR boundary
Error boundaries are components that
- catch JavaScript errors anywhere in their child component tree
- log those errors
- display a fallback UI instead of the component tree that crashed.
A class component becomes an error boundary if it defines new lifecycle methods: componentDidCatch(error, info) or static getDerivedStateFromError()
<ErrorBoundary>
<YourComponent/>
</ErrorBoundary>
Below are the cases in which error boundaries don't work
1. Inside Event handlers
2 .Asynchronous code using setTimeout or requestAnimationFrame callbacks
3. During Server side rendering
4. When errors thrown in the error boundary code itself
In the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to emit critical errors on next renders.
React did not provide any way to handle them gracefully in components, and could not recover from them.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
<ErrorBoundary>
<YourComponent/>
</ErrorBoundary>
Thanks!
AND GOOD LUCK
Simple React App from lecture
Full version of App from lecture
1.5 hour YouTube video to clear some basic gaps
ReactJS
By Victoria Budyonnaya
ReactJS
- 380