Before you’re going to hate it, then you’re going to love it.
Concurrent Render(throughout 16)
In JSConf Iceland ’18, Dan God mentioned Concurrent Render involving both CPU and IO.
Time Slicing means solving problems on the left, Suspense means solving problems on the right. What they collectively address is to improve the user experience and make it interactive in more scenarios. The Fiber architecture is the cornerstone of both.
Time Slicing
In versions prior to 16, the rendering process can be imagined as a one-time 30-meter dive, during which nothing else can be done (Stack Reconciler);
Pain point summary:
- Render to the end once
- Unable to adjust the sequence of higher priority events
Taking the diving example above as an example, it is now possible to dive 10 meters at a time in 3 chunks; Chunks are connected to each other through linked lists. A task with a higher priority is inserted between chunks, and the previous task is discarded.
After Fiber is enabled, the method of retrieving asynchronous data should be placed in the lifecycle hooks (Phase 2) after Render, since the lifecycle hooks (Phase 1) before Render are executed multiple times
Note: the rendering time of the original component is not reduced (or even increased), but the user feels smoother.
RequestIdleCallback (): With this API, the browser can handle low-priority tasks in idle time.
Suspense (16.6, 16.8, 16.9)
Suspense means to be able to pause rendering of the current component and continue rendering when something is done.
- Code Splitting (16.6, online): Lazy file loading. The previous implementation was react-loadable
- Concurrent mode (16.8, Q2 2019): Lazy file loading while doing other interactions;
- Data fetching(version 16.9, mid-2019): Dynamic data fetching;
import React, { lazy, Suspense } from 'react'
const OtherComponent = lazy((a)= > import('./OtherComponent'))
function MyComponent() {
return (
<Suspense fallback={<div>loading...</div>} ><OtherComponent />
</Suspense>)}Copy the code
For a simple idea of preloading, see Preload
const OtherComponentPromise = import('./OtherComponent');
const OtherComponent = React.lazy((a)= > OtherComponentPromise);
Copy the code
Render New return type
Render () added a number of return types to Render () in Act16. The following return types are supported so far:
- React elements.
- Arrays and fragments.
- Portals.
- String and numbers.
- Booleans or null.
render
Render () supports returning Arrays to save one parent, as shown below:
const renderArray = () => [
<div key="A">A</div>
<div key="B">B</div>
]
Copy the code
Render () supports returning arrays similar to Fragments(16.2), which can be used without writing keys.
Portals
Render the React child node to the specified node
Example: Implement a Modal component, demo
As for the phenomenon of Portals bubbling to the parent’s sibling, demo, I think it can be implemented like this: If the component returns a Portal object, copy the event on the parent of the component to that component. It doesn’t actually bubble up to the sibling of the parent.
Error Boundaries
React 16 provides a new error-catching hook componentDidCatch(Error, errorInfo) that traps errors thrown by a child component during its life cycle, preventing global crashes. demo
ComponentDidCatch does not catch the following errors
- Errors thrown by the event mechanism (errors in the event do not affect rendering)
- Error Boundaries Errors thrown by yourself
- An error occurred asynchronously
- Server side rendering
Server side rendering
Server rendering is usually used as an optimization of last resort, so here’s a primer on how React 16 optimizes it.
The React 16 version introduced react.hydrate (), which waterfloods relevant events into HTML pages and compares the HTML generated by the front end with the HTML text that the server sends to the front end. If the two are inconsistent, replace the text content generated by the front end with the text content generated by the server (ignoring the attribute).
Custom attributes are supported
In The React 16 version, custom attributes are supported (data-xxx is recommended), so React can maintain a whitelist of attributes less. This is also a significant factor in reducing the size of React 16.
The Context (16.3, 16.6)
Context uses global in a componentized way, sharing global information about authenticated users, preferred language (internationalization), and so on, rather than passing it through layers of components.
Here are some more redundant passes:
<Page riderId={riderId} />
// ... which renders ...
<RiderDetail riderId={riderId} />
// ... which renders ...
<RiderLevel riderId={riderId} />
// ... which renders ...
<Avatar riderId={riderId} />
Copy the code
itself (Component Composition idea) can be passed before Context as follows:
function Page(props) {
const avatar = <Avatar riderId={props.riderId} />
return <RiderDetail avatar={avatar} />
}
<Page riderId={riderId} />
// ... which renders ...
<RiderDetail avatar={avatar} />
// ... which renders ...
<RiderLevel avatar={avatar} />
// ... which renders ...
{ props.avatar }
Copy the code
Here is an example of writing using Context as follows:
const RiderContext = React.createContext(1) // This is the default value
function Page(props) {
const riderId = props.riderId
return( <RiderContext.Provider value={riderId}> <RiderDetail /> </RiderContext.Provider> ) } function RiderDetail() { return <RiderLevel /> } class RiderLevel extends React.Component { static contextType = RiderContext render() { return <Avatar avatar={this.context} />; }}Copy the code
New Life Cycle (16.3)
In future 17, the following lifecycle hooks will be removed:
componentWillMount()
The API was removed for two reasons:- Server render: Executing render immediately after componentWillMount execution causes methods executed in componentWillMount (fetching data, subscribing events) to not be executed.
- Concurrent Render: In Fiber, the hook before Render is called multiple times, executing the subscription event in componentWillMount causes a memory leak;
ComponentDidMount (componentWillMount, componentDidMount, componentWillMount);
componentWillReceiveProps(nextProps)
The API was removed based on the following considerations:- The semantics don’t quite fit logic
Here’s an example: For example, whenever you switch a TAB, you need to retrieve the data from the current page, which is usually the case:
componentWillReceiveProps(nextProps) {
if(nextProps.riderId ! = =this.props.riderId) {
fetchData()
}
}
Copy the code
The new hook getDerivedStateFromProps() is puter. All it does is compare the newly passed property to the current state value, and update the current state if they are inconsistent. Before componentWillReceiveProps () to get the data logic mentioned in Concurrent render should also mentioned the rear to componentDidUpdate ().
getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.riderId ! == prevState.riderId) {return {
riderId: nextProps.riderId
}
}
// Return null to indicate that state is not used for updates
return null
}
Copy the code
componentWillUpdate()
: Currently understood as andcomponentWillMount
Same thing
In React 16.3, there are two new life cycles:
-
GetDerivedStateFromProps (nextProps prevState) : more semantic, used to replace componentWillMount () and componentWillReceiveProps (nextProps);
-
GetSnapshotBeforeUpdate (prevProps, prevState): You can pass the result returned by this hook into the third parameter of componentDidUpdate to achieve DOM data unity. Instead of componentWillUpdate();
Update on Async Rendering
The React. Memo (16.6)
React.memo is a higher-order component that gives stateless components shouldComponentUpdate() and PureComponent capabilities in stateful group values.
const MyComponent = React.memo(function MyComponent(props) {... })Copy the code
Hooks (16.7)
Prior to React 16.7, React had two forms of components, stateful components (classes) and stateless components (functions). Hooks are used to enable previously stateless components to become stateful. This is more in line with the functional programming espoused by React.
Next, I’ll review the two core apis of Hooks, useState and useEffect
useState
UseState returns the status and a function that updates the status
const [count, setCount] = useState(initialState)
Copy the code
Using Hooks is more intuitive and concise than using class
function App() {
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked {count} times</p>
<button onClick={()= > setCount(count + 1)}>
Click me
</button>
</div>)}Copy the code
useEffect(fn)
This hook is executed after each render. Think of it as a componentDidMount, componentDidUpdate, componentWillUnmount. Therefore, the advantages of using useEffect are as follows:
- Can be avoided
ComponentDidMount, componentDidUpdate
Writing repetitive code; - You can write the association logic into one
useEffect
; (in the old days it had to be written in different life cycles);
The future of the React
This year’s React Conf shows how React has been on a steady upward trajectory since its inception, knocking Jquery off its throne at this point in 2018. React still has a long way to go.
A link to the
- reactjs.org