Recently, I was writing React-Native and implemented some optimization items while the requirements were almost completed in these two days.
Recorded in the
Life sucks
Performance
See React Native Performance
Check the performance
Open the developer menu (shake the phone to open it) 👉 Open the Show Perf Monitor and you can see the display box below
Both UI and JS frames remain at 60 frames, which is optimal.
JS single thread
All event processing, API requests, etc. are done on this thread, and when this. SetState has a large amount of data, the state change will cause re-render, during which all javascripts controlled animations will get stuck frames
For example, when switching routes, the frame number will have obvious jitter. If you have something to do at componentDidMount it’s going to make the route transition animation very slow. (Some of the solutions you can try are described below
The development environment performs worse than the production environment
In the development environment, the framework has many other operations such as warning error output, type detection, and so on.
If you want to test performance, it’s best to do it in the Release package. It’s more accurate.
Remove console.* from production environment
During development, there are many console.* directives to help with debugging. And some dependent libraries also have console.* These statements can be a huge drain on JavaScript threads. You can remove console.* from production via Babel.
-
Installing a plug-in
npm i babel-plugin-transform-remove-console --save-dev
-
Configure the. Babelrc file
{ "env": { "production": { "plugins": ["transform-remove-console"]}}}Copy the code
Used when processing large lists of data<FlatList />
The FlatList component is more suitable for displaying long lists and specifies the appropriate getItemLayout method, which skips the layout calculation for rendering items and uses the given configuration directly (see ☝️ for details).
Relying on lazy loading
Before the framework can execute the written business code, the code needs to be loaded and parsed in memory. The larger the code volume, the more time this process takes, resulting in the slow rendering of the first screen. Often, some pages or components are never accessed by the user at all. This can be optimized by lazy loading.
There are examples on the website
VeryExpensive.js
import React, { Component } from 'react';
import { Text } from 'react-native';
// ... import some very expensive modules
// You may want to log at the file level to verify when this is happening
console.log('VeryExpensive component loaded');
export default class VeryExpensive extends Component {
// lots and lots of code
render() {
return <Text>Very Expensive Component</Text>; }}Copy the code
Optimized.js
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';
let VeryExpensive = null; // Define variables
export default class Optimized extends Component {
state = { needsExpensive: false }; // Define internal state to control whether the component needs to be loaded
didPress = (a)= > {
// When an event that requires a component to be loaded is triggered
if (VeryExpensive == null) { // Do not repeat references
VeryExpensive = require('./VeryExpensive').default; // Assign a reference to the component to the defined variable
}
this.setState((a)= > ({
needsExpensive: true.// Change the state of the control to trigger the component re-render
}));
};
render() {
return (
<View style={{ marginTop: 20}} >
<TouchableOpacity onPress={this.didPress}>
<Text>Load</Text>
</TouchableOpacity>
{this.state.needsExpensive ? <VeryExpensive /> : null}
</View>); }}Copy the code
Optimize component rendering times
React rerenders components when internal state or externally passed props change. A large number of components that have to be rerendered in a short period of time can cause serious performance problems. There’s a point here that you can optimize.
- use
PureComponent
Let components compare themselvesprops
In practice, this controlled approach is more reliable than purely functional components. Or in theComponent
The use ofshouldComponentUpdate
Method to control the updating/re-rendering of components by conditional judgment. - use
PureComponent
Note that this component is in shallow comparison state, ifprops
If you have a large number of reference type objects, the internal changes of these objects will not be compared. Avoid complex data structures when writing code - Fine-grained components, split dynamic/static components. Unified planning is required after the project is stable and has a certain scale.
- Learning immutable – js * * * *
Asynchronous, callback
JavaScript is single-threaded, taking advantage of its asynchronous nature, and some hook callbacks.
For example, when routing switches occur in componentDidMount, Here can use InteractionManager. RunAfterInteractions () will need to perform operations on runAfterInteractions callback.
componentDidMount() {
InteractionManager.runAfterInteractions((a)= > {
// your actions})}Copy the code
Note that the InteractionManager listens for all animations/interactions to complete before triggering callbacks in the runAfterInteractions. If you have long animations or interactions in your project, long waits may occur. Therefore, due to the uncontrollability of InteractionManager, use it according to the actual situation.
Some animation feedback in React-Native, such as TouchableOpacity, will respond to onPress when touched and its transparency will change. If there is complex operation in onPress during this process, it is likely to lead to transparent feedback of the component. You can then wrap the actions in onPress in requestAnimationFrame. Styled – Component Here is my practice (using styled- Component)
import styled from 'styled-components'
export const TouchableOpacity = styled.TouchableOpacity.attrs({
onPress: props= > () => {
requestAnimationFrame((a)= > {
props.onPressAsync && props.onPressAsync()
}, 0)}})` `
Copy the code
Here we change onPress to perform the onPressAsync incoming operation in the requestAnimationFrame callback.
Similarly, this is done in the onReachEnd of the FlatList to avoid the lag of rolling back in iOS.
Above, some practical optimizations of recent react-native writing are recorded.
The last
The way ahead is so long without ending, yet high and low I’ll search with my will unbending.
May love & peace be with you
reference
- React native Performance
Author: Roy Luo
React Native Performance Optimization