# React Docs Notes
---
## Main Concepts
---
### JSX Represents Objects
Babel compiles JSX down to `React.createElement()` calls (by [babel-plugin-transform-react-jsx](https://github.com/babel/babel/tree/7.0/packages/babel-plugin-transform-react-jsx)) and return an element tree.
These two examples are identical:
```javascript
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
```
```javascript
const element = React.createElement(
'h1', // type
{className: 'greeting'}, // [props]
'Hello, world!' // [...children]
);
```
---
which creates object like this:
```javascript
// Note: this structure is simplified
const element = {
type: 'h1', // type: string | function | component
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
```
> An element is a plain **object** describing a component instance or DOM node and its desired properties.
---
### Rendering
:::info
1. `render` (depending on the return value of `shouldComponentUpdate`)
2. Virtual DOM Diff ([Immutable.js](https://immutable-js.github.io/immutable-js/) recommended)
:::
- `false`, `null`, `undefined`, and `true` are valid children. They simply don’t render.
```javascript
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
```
- Some of “falsy” values are still rendered. e.g. 0 would be rendered.
```javascript
<React.Fragment>
{props.messages.length && <div>There are messages.</div>}
</React.Fragment>
```
---
### Reconciliation
> When you use React, at a single point in time you can think of the `render()` function as creating a **tree** of React elements. On the next state or props update, that `render()` function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.
:::info
1. Two elements of different types will produce different trees.
2. The developer can hint at which child elements may be stable across different renders with a key prop.
:::
#### The Diffing Algorithm
- **Elements of different types**: unmounts elements and have their state destroyed.
e.g. from `<a>` to `<img>`, or from `<Article>` to `<Comment>`, or from `<Button>` to `<div>`
- **DOM element of the same type**: only updates the changed attributes
- **Component elements of the same type**: updates props, which calls `componentWillReceiveProps()` and `componentWillUpdate()`, then `render()`
- **Recursion**: `key` attribute (e.g. [key=index](https://reactjs.org/redirect-to-codepen/reconciliation/index-used-as-key), [key=id](https://reactjs.org/redirect-to-codepen/reconciliation/no-index-used-as-key))
- Unique - A key cannot be identical to that of a sibling component.
- Static - A key should not ever change between renders.
####
Render Props: a simple technique for sharing code between React components using a prop whose value is a function.
- **Higher Order Component**: is a function that takes a component and returns a new component.
---
### State Updates May Be Asynchronous
React may batch multiple `setState()` calls into a single update for performance.
e.g. [not using function](https://codepen.io/stuku/pen/bQpmKo?editors=0010), [using function](https://codepen.io/stuku/pen/wQGYYr?editors=0010)
---
### Handling Events
```javascript
// okay
render() {
return <MyInput onChange={e => this.props.update(e.target.value)} />
}
// or
update(e) {
this.props.update(e.target.value);
}
render() {
return <MyInput onChange={this.update.bind(this)} />
}
```
---
```javascript
// better
constructor(props) {
super(props);
this.update = this.update.bind(this);
}
// or
update = (e) => {
this.props.update(e.target.value);
}
render() {
return <MyInput onChange={this.update} />
}
```
[Try it on CodePen](https://codepen.io/stuku/pen/bQLOvO?editors=0010)
---
### Pure Component and Stateless Component
#### When to Use Pure Components?
- no nested data structure
- stateless but lifecycle methods needed
#### When to Use Stateless Components?
very small UI view where re-render cost won’t matter that much
(`React.memo` has been added as as an alternative in React 16)
---
### Integrating with Other Libraries
within HOC ([e.g.](https://codepen.io/gaearon/pen/PmWwwa?editors=0010))
---
## Changes in React 16
---
### React Fiber: an reimplementation of React’s core algorithm
- priority-based update system
---
### New Render Return Types: Fragments and Strings
```javascript
render() {
// No need to wrap list items in an extra element!
return [
// Don't forget the keys :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
// or
render() {
return "Look ma, no spans!";
}
```
[Try it on CodePen](https://codepen.io/stuku/pen/VVaoqg?editors=0010)
---
### Error Boundary
catch errors **during rendering, in lifecycle methods, and in constructors of the whole tree below them**, and display a fallback UI -- which is an implication -- as of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree ([e.g](https://codepen.io/gaearon/pen/wqvxGa?editors=0010)).
Note:
Error boundaries do **not** catch errors for:
- Event handlers
- Asynchronous code (e.g. setTimeout)
- Server side rendering
- Errors thrown in the error boundary itself (rather than its children
---
```javascript
class PotentialError extends React.Component {
constructor(props) {
super(props);
this.state = { error: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { error: true };
}
componentDidCatch(error, info) {
this.setState({ error, info });
}
render() {
if (this.state.error) {
return <h1>Error: {this.state.info && this.state.info.componentStack}</h1>;
}
return this.props.children;
}
}
```
---
### Portals
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
```javascript
render() {
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode
);
}
```
[Try it on CodePen](https://codepen.io/gaearon/pen/yzMaBd)
---
### Support for Custom DOM Attributes
```javascript
// Your code:
<div mycustomattribute="something" />
```
```javascript
// React 15 output:
<div />
```
```javascript
// React 16 output:
<div mycustomattribute="something" />
```
[More attribute behaviors](https://github.com/facebook/react/blob/master/fixtures/attribute-behavior/AttributeTableSnapshot.md)
---
### Component Lifecycle Changes
- `componentWillMount`, `componentWillReceiveProps`, and `componentWillUpdate` will be aliased with an “UNSAFE_” prefix
- `getDerivedStateFromProps` and `getSnapshotBeforeUpdate` is being added
[Check out this lifecycle diagram](http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)
---
### Fragments
group a list of children **without** adding extra nodes to the DOM.
```javascript
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
<Fragment key={item.id}> // or <></>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment>
))}
</dl>
);
}
```
Note: `key` is the only attribute that can be passed to `Fragment`
---
### `React.memo`
similar to PureComponent
```javascript
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
const MyComponent = React.memo(props => (
/* only rerenders if props change */
), areEqual);
```
Note:
Unlike the `shouldComponentUpdate()` method on class components, the `areEqual` function returns `true` if the props are equal and `false` if the props are not equal. This is the **inverse** from shouldComponentUpdate.
---
### `React.lazy`: Code-Splitting with Suspense
```javascript
import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense maxDuration={1000} fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
);
}
```
---
### New Context API
```javascript
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
```
---
```javascript
class ThemedButton extends React.Component {
// only accessible in render method
render() {
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}
```
---
```javascript
// or
class ThemedButton extends React.Component {
static contextType = ThemeContext;
componentDidMount() {
let value = this.context;
/* perform a side-effect at mount using the value of ThemeContext */
}
/*
componentWillReceiveProps(nextProps, nextContext) {}
shouldComponentUpdate(nextProps, nextState, nextContext) {}
componentWillUpdate(nextProps, nextState, nextContext) {}
componentDidUpdate(nextProps, nextState, nextContext) {}
*/
render() {
let value = this.context;
/* render something based on the value of ThemeContext */
}
}
```
---
```javascript
// or
function ThemedButton(props, context) {
return (
<Button theme={context.theme} />
);
}
ThemedButton.contextTypes = {
theme: React.PropTypes.string.isRequired
}
```
Try it on CodePen: [React 15](https://codepen.io/stuku/pen/BGKgYO?editors=0010), [React 16](https://codepen.io/stuku/pen/ZmWNqm?editors=0010)
---
### Refs: `React.createRef`, `React.ForwardRef`
```javascript
constructor(props) {
super(props);
// recent way
this.textInput = null;
this.myRef = el => {
this.textInput = el;
};
// in React 16
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
```
---
```javascript
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
```
[Try it on CodePen](https://codepen.io/stuku/pen/bQwqZG?editors=0011)
---
### Dev Tool: [React Profiler](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)
---
ref:
- [React Docs](https://reactjs.org/docs/hello-world.html)
- [State updates might be asynchronous](https://stackoverflow.com/questions/45248204/state-updates-might-be-asynchronous)
- [Lin Clark - A Cartoon Intro to Fiber - React Conf 2017](https://youtu.be/ZCuYPiUIONs)
- [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture)
- [Update on Async Rendering](https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html)