Alfian Busyro
JavaScript and Web Performance Addict
by Alfian Busyro
Repaint - also known as redraw - is what happens whenever something is made visible when it was not previously visible, or vice versa, without altering the layout of the document.
- Opera
What is reflow ?
DOM changes will trigger reflow,
which will trigger browser to calculate the layout
Less repaint and reflow
equal to more optimized
How to avoid repaint in React
class MyComponent extends React.PureComponent {
render() {
const { data } = this.props
return (
<ul>
{data.map((item, i) => {
return <li key={item.id}>{item.title}</li>
})}
</ul>
)
}
}
How to avoid repaint in React
shouldComponentUpdate(nextProps, nextState) {
return (
(!isEqual(this.props.a, nextProps.a)) ||
(!isEqual(this.state.data, nextState.data))
)
}
// From
export default class AwesomeComponent extends React.Component {
// To
export default class AwesomeComponent extends React.PureComponent {
How to avoid reflow in React
If you have please use ref instead
Debugging reflow and repaint
https://github.com/maicki/why-did-you-update
Understanding Modern React's Life Cycle
class HelloReact extends React.Component {
state = {
a: 1, b: 2
}
increase = async () => {
const increaseStateVal = async () => {
const {a, b} = this.state
this.setState({
a: a+1,
b: b+1,
})
}
await increaseStateVal()
}
render() {
const {a, b} = this.state
this.increase()
return (
<>
<div>a: {a}</div>
<div>b: {b}</div>
</>
)
}}
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
JavaScript is single thread non blocking programming language
export default class AwesomeComponent extends Component {
glamorousAsyncProcess() {
// heavy redux action
}
constructor() {
super()
// don't
this.glamorousAsyncProcess()
}
getDerivedStateFromProps(props, state) {
// don't
this.glamorousAsyncProcess()
}
async populateUser() {
// populate 1M Users
await this.props.populateMillionUsers()
}
render() {
//don't
this.populateUser()
return(
<div>
<span>
Hello World! with heavy process on the back
</span>
</div>
)
}
}
class AwesomeComponent extends Component {
glamorousAsyncProcess() {
// heavy redux action
}
constructor() {
super()
this.glamorousAsyncProcess = this.glamorousAsyncProcess.bind(this)
}
componentDidMount() {
// do
this.glamorousAsyncProcess()
}
componentDidUpdate() {
// do
this.glamorousAsyncProcess()
}
render() {
return(
<div>
<span>
Hello World! with heavy process on the back
</span>
<button onClick={this.viewContacts} >
Press Me!
</button>
</div>
)
}
}
The Event Loop
Jake Archibald:
Philip Roberts:
import nextFrame from 'next-frame';
// ...
for (let recording of recordingsJSON) {
await nextFrame(); // This is all we need to add!
mergeRecordingToLocalDatabase(recording);
}
More details in here:
https://calibreapp.com/blog/react-performance-profiling-optimization/
By Alfian Busyro
Goals: To be aware of performance impact from a line of code, produce a better performant code for the better application and to reduce potentially buggy code.