---
# System prepended metadata

title: React Docs Notes

---

# 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)
