in this section, we will find out the flow rendering of React.
The component Lifecycle
- mounting: when an instance of a component is created and inserts into the DOM
constructor()UNSAFE_componentWillMount()UNSAFE_componentWillReceiveProps()static getDerivedStateFromProps()render()componentDidMount()
- updating: props or state change
shouldComponentUpdate()UNSAFE_componentWillUpdate()UNSAFE_componentWillReceiveProps()static getDerivedStateFromProps()render()getSnapshotBeforeUpdate()componentDidUpdate()
- unmounting: when an instance component is removed from the DOM
componentWillUnmount()
constructor(props)
- a place to initialize variables, states, event handler (binding this context)
- run only one time when the instance component is created
- call super(props) at the beginning of the function
- don’t call setState() here
shouldComponentUpdate(nextProps, nextState
)
- as default, it always returns true
- if it returns false, the orther lifecycle will not be invoked
- In the future, React may treat
shouldComponentUpdate()
as a hint rather than a strict directive, and returningfalse
may still result in a re-rendering of the component.
static getDerivedStateFromProps(nextProps, prevState)
- rarely use.
- invoked right before calling render()
- is used for applying value props to state
- return an object to update the state, or null to update nothing
- if it’s defined, 3 legacies lifecycle will not effect:
+ UNSAFE_componentWillMount()
+ UNSAFE_componentWillUpdate()
+ UNSAFE_componentWillReceiveProps()
getSnapshotBeforeUpdate(prevProps, prevState)
- invoked right before the element has been rendered/updated
- capture some information from the DOM before it is potentially changed
- this output will be the third variable snapshot of componentDidUpdate()
- is used for capturing and passing the old variable of props and state to componentDidUpdate()
render()
- a required function
- invoke when shouldComponentUpdate() is true
- examine
this.props
andthis.state
- return:
+ React DOM
+ Arrays React DOM
+ ReactDOM portals (aim to render element in a different position)
+ value of number, string, boolean
componentDidMount()
- invoke after rendering of the first time
- a good place to set up any subscriptions/events. don’t forget unsubscriptions in componentWillUnMount()
- be careful with infinitive loop
componentDidUpdate(prevProps, prevState, snapshot)
- invoke after rendering from the second time
- be careful with infinitive loop
componentWillUnmount()
- invoke when the intance component is removed
- don’t setState() here
Error Handling: (only use one of above options)
1. static getDerivedStateFromError(error, info)
- invoke when an error has been thrown
- is used for logging error and return new state to render error UI
2. componentDidCatch(error, info) # will be deprecate
- invoke when an error has been thrown
- is used for logging error and call setState() here to render error UI
Legacy lifecycle method (wouldn’t touch them)
# invoked just before mounting occurs, before render()
UNSAFE_componentWillMount()# previously named componentWillReceiveProps. work until version 17
UNSAFE_componentWillReceiveProps(nextProps)# previously named componentWillUpdate. invoked just before rendering when new props or state are being received
UNSAFE_componentWillUpdate(nextProps, nextState)
Reconciliation
- React’s “diffing” algorithm
- render() will return a tree of React elements. When we have an update (re-render), React then needs to figure out how to efficiently update the UI to match the most recent tree. React implements a heuristic O(n) algorithm based on two assumptions:
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 akey
prop. - Whenever the root elements have different types, React will tear down the old tree and build the new tree.
- If there is the same type but changing attributes, the React only update the attributes.
- Recursive child: React compare the element with their order. the example below will render new the 3 elements because of the wrong position.
- To solve this issue, React supports a
key
attribute
React API
1. setState(updater, [callback])
- enqueues changes to the component and tells React that this component and its children need to be re-rendered with the updated state
setState()
will always lead to a render() unlessshouldComponentUpdate()
returnsfalse
- the callback invokes after the component is re-rendered
- In depth: When and why are
setState()
calls batched inside event-handler?
+ inside a React event handler, they will produce only a single re-render at the end of the event.
+ But it would apply intermediately change when we call them in Promise callback. React 17 would be batched all updates into once, and for a temporary fix please useReactDOM.unstable_batchedUpdates(function(){...})
2. forceUpdate([callback])
- skipping shouldComponentUpdate() and force calling render()
- for child components, trigger the normal lifecycle methods including the
shouldComponentUpdate()
. Hence, if theshouldComponentUpdate()
return false, child wouldn’t re-render.
PureComponent
- with Component, when call setState, it always leads to render()
- a useful react component override the shouldComponentUpdate() that helps to shallow detect the change of props
- shallow detect only finds a change in the first depth level
React.memo([functional Component], areEqual(prevProps, nextProps))
- same with PureComponent, but be used for the functional component
- https://reactjs.org/docs/react-api.html#reactmemo