Profiler
This component implements a simple test of the rendering time of the wrapped component, mainly the settingid
Attributes andonRender
Function returns the corresponding test results. amongonRender
The return values of are:
id: string
-SubmittedProfiler
Treelikeid
. If there are multiple profilers, it can be used to distinguish which part of the tree has been “committed”.phase: "mount" | "update"
-Determine whether the re rendering is caused by the first loading of the component tree, or by changes in props, state, or hooks.actualDuration: number
-This update is in the renderingProfiler
And the time it spends on its children. This value shows how well memory can perform. (e.gReact.memo
,useMemo
,shouldComponentUpdate
)。 Ideally, this value should drop significantly after the first load, since the offspring will only be re rendered due to specific prop changes.baseDuration: number
-InProfiler
The last time each component in the treerender
The duration of the test. This value estimates the worst rendering time. (for example, when it is loaded for the first time or when the component tree does not use memoization).startTime: number
-The timestamp of react start rendering in this update.commitTime: number
-The timestamp of the end of the react commit phase in this update. In a commit, this value is shared among all profilers and can be grouped on demand.interactions: Set
-When updates are made,“interactions”Will be tracked. (for example, whenrender
perhapssetState
When called).The above is quoted fromReact website
Show the effect through a simple demo:
import React, { Component, Profiler } from "react";
import styles from "./styles.module.less";
class Test extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
console.log("test");
}
callback = (id, ...props) => {
let params = {
...props,
};
console.log (` time to view ${ID}, params));
};
render() {
return (
<div className={styles.contain}>
<Profiler id="testPro" onRender={this.callback}>
< button > test
</Profiler>
</div>
);
}
}
export default Test;
The demo above is used to test the rendering speed of the button component. The result of the console printing is as follows:
Do not use ES6
Although it’s probably impossible to have a convenient ES6, to write that long string of code by yourself, but I still took a look at the basic.
The main differences are the syntax of creating components
type | es6 | Do not use ES6 |
---|---|---|
class | class Counter extends React.Component {} |
var Counter = createReactClass({}); |
state | this.state |
getInitialState: function() {return {count: this.props.initialCount};} |
bind | this.handleClick = this.handleClick.bind(this) Or use the arrow function |
Automatic binding |
mixin | I won’t support it | support |
Don’t use JSX
As I said before,JSX
justreact
The syntax of sugar, so that you can more easily program, if it is their own configurationwebpack
, don’t want more cumbersome configurationJSX
Related content, not usedJSX
It’s the same, but the originalJSX
Change the way you write it toReact.createElement()
Function.
There is a simplified way to write it
const e = React.createElement
ReactDOM.render(
e('div', null, 'Hello World'),
document.getElementById('root')
);
coordinate
This section mainly talks aboutreact
For updating componentsdiffing
Algorithm design decision, in order to make the program more accurate implementation of the purpose of the writer, for the realization of some functions, part of the parameter configuration, need to be as far as possibleCoordinate demand satisfaction and performance consumption
Diffing algorithm
- Compare different root elements: if the root element is different, directly unload the original root element and reload the new one.
The life cycle is as follows:componentWillUnmount()
: uninstall component, existingstate
DestructioncomponentWillMount()
: new element will start loading, newstate
initializationcomponentDidMount()
: component loading completed - Comparing elements of the same type: if the elements are consistent, it changes the attribute in the element. If the style changes, it updates the changed item.
- Compare component elements of the same type: because the type is consistent, the component instance will be retained to ensure the consistency of the component state rendering. Therefore, the internal life cycle only needs to call the updated part
componentWillReceiveProps()
: whenprops
It can be used internally when changes occurthis.setState()
To updatestate
Call update here does not trigger additionalrender
。componentWillUpdate()
: whenprops
andstate
Execute when changes occur, except initializationrender
Other thanrender
After that, it can not be used internallythis.setState()
After the call, thenextProps
andnextState
Update existingthis.props
andthis.state
。
After the life cycle, call the previousdiffing
To update and render the whole component tree.
PS: in this algorithm, if you insert an element into an existing element, the entire root element will be unloaded first and a new element will be reconstructed. This will cause a large performance consumption, which is probably one of the reasons that react does not recommend DOM operation
PS: the performance consumption of algorithm switching between different types is much higher than that of the same type, so when the output is similar, the same type of components should be used as much as possible
Keys
When we use traversal array rendering, we need to set thekey
But try to avoid using the subscript of an array as the valuekey
Value input. Because doing so may cause the contents of controllable components to display exception when inserting and rearranging arrays.
At the same time, if we use methods such as random numbers to generate akey
Value (e.g. usingMath.random()
)And use it every timerender
Will trigger the operation of unloading elements and refactoring components, which will cause a lot of unnecessary performance consumption, as well as the state loss of some sub components.
Refs & DOM
As I said before, it was approvedRefs
Forward to get instances of common elements or component elements, so as to realize the query outside the data flowdom
Modify (above)refs
The forwarding method only supportsreact16.3
Above).
- apply
refs
The following is the case:
Manage focus, text selection or media playback.
Trigger force animation.
Integrated third partyDOM
Library.
Avoid usingrefs
To do anything that can be done declaratively.
- Expose the child component DOM to the parent component
react
It’s not recommended to do this unless you have to
In version 16.3 and above, you can useReact.forwardRef
realization
Below 16.3 or want to use more flexiblyref
, you can use some aliasesprops
Pass downref
For example:<Comp inputRef = { this.ref } />
CallbackRefs
Callbackrefs
It’s like receiving a child component in the parent componentref
Callback result, which is modified according to the value returned by the child component. In the child component, the function of the parent component is called as the callback resultref
To form a function oriented middlewareref
Penetration, the following code is quoted fromhttps://zh-hans.reactjs.org/d…
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} /> </div>
);
}
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el} />
);
}
}
It can be seen from the above exampleCustomTextInput
Component, callingprops.inputRef
Function asref
, which is passed back to the parent componentParent
Component, and finally form the parent component usage controlthis.inputElement
Get subcomponentsDOM
The purpose of the project.
It should be noted that the callback should be avoided as far as possibleref
Write it as an inline function. Because the inline function will be called twice when it is updated, it is better to write it as a binding function of a class
//Inline function
<div test = {()=>{
this.setState({ test:false })
}}>
//Class
constructor(props){
this.state={ test:true }
this.changeTest= this.changeTest.bind(this)
}
//Or use the arrow function
changeTest = () => {
this.setState({ test:false })
}
Render Props
Render prop is a function that tells the component what to render
For example, in common use, we want to define a nice looking box. There may be a lot of unknown things in the box, but the outer packaging of the box is consistent. At this time, we want to have a component that can customize the received rendering content without changing the outer layer. Based on this, the common methods are as follows:
class Box extend Component{
render(){
return (
<div style={padding:2,mrgin:4,backgroundColor:'red'}>
{this.props.children}
</div>
)
}
}
In the above example, we defined a box with a red bottom, an inner border of 2px, and an outer border of 4PXthis.props.children
To receive the rendered content from the outside world, and directly package it from the outside world
<Box>{'test: input a props children'}</Box>
This is a simple exampleRender Props
In this case, we don’t need to define achildren
Ofprop
Attribute, becausereact
Defaultchildren
Property unless you manually change it yourself. In addition, you can also use your own defined attributes, such as:
<Test render={(test)=>{
return <div> {test} <div>
}}
//Define a red box as above
function Test(props){
return (
<div style={padding:2,mrgin:4,backgroundColor:'red'}>
{props.render}
</div>
)
}
In addition, useRender Props
Can be very convenient to generate a hoc, you can put the rendering content in the box, dynamic through the parameters into it.
PS: in useReact.PureComponent
When generating components, it may causeRender Props
The problem of failure, because
React.PureComponent
InshouldComponentUpdate()
Only shallow comparison of objects. If the object contains complex data structure, it may be unable to check the deep differences, resulting in wrong comparison results. (quoted fromhttps://zh-hans.reactjs.org/d…)
The result is thatrender
Every one of themprops
It’s all different, which destroys the rendering.—-However, I have tested it for a long time according to the example of the official website, and I have not seen any abnormal phenomenon🙁Then find the difference and fill the hole