# React 性能优化(一): 减少不必要的组件更新
在 React 里会遇到这样一个场景: 父组件的状态发生变化会触发父组件的更新, 随后连同子组件一起更新.可是如果子组件没有和父组件产生依赖, 更新子组件其实是没有必要的.举个例子如下:
我是爸爸
1
我是儿子
class Son extends React.Component { render() { console.log("触发儿子组件render"); return <p>我是儿子</p>; } } export default class App extends React.Component { constructor() { super(); this.state = { n: 1, }; } render() { return ( <> <p>我是爸爸</p> <p>{this.state.n}</p> <button onClick={() => { this.setState({ n: this.state.n + 1 }); }} > +1 </button> <Son /> </> ); } }
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
在 console 里可以看到, 每当+1
按钮被点击, Son
组件的 render 函数就会被执行一次.那我们应该通知 React 不要更新子组件.
# shouldComponentUpdate
这里是这个钩子的详细定义和使用.
我是爸爸
1
我是儿子
class Son extends React.Component { shouldComponentUpdate() { return false; } render() { console.log("触发儿子组件render"); return <p>我是儿子</p>; } } export default class App extends React.Component { constructor() { super(); this.state = { n: 1, }; } render() { return ( <> <p>我是爸爸</p> <p>{this.state.n}</p> <button onClick={() => { this.setState({ n: this.state.n + 1 }); }} > +1 </button> <Son /> </> ); } }
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# PureComponent
如果不想每次手动调用上面的钩子, React 提供了PureComponent
来解决同样的问题:
我是爸爸
1
我是儿子
class Son1 extends React.PureComponent { render() { console.log("触发儿子组件render"); return <p>我是儿子</p>; } } export default class App1 extends React.Component { constructor() { super(); this.state = { n: 1, }; } render() { return ( <> <p>我是爸爸</p> <p>{this.state.n}</p> <button onClick={() => { this.setState({ n: this.state.n + 1 }); }} > +1 </button> <Son1 /> </> ); } }
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
注意
值得一提的是,
PureComponent
中shouldComponentUpdate
对props
做得只是浅层比较,不是深层比较,如果props
是一个深层对象,就容易产生问题。比如,两次渲染传入的某个
props
都是同一个对象,但是对象中某个属性的值不同,这在PureComponent
眼里,props
没有变化,不会重新渲染,但是这>明显不是我们想要的结果。
# 函数组件使用
在函数组件里, React 提供了React.memo
来实现自定义更新:
我是爸爸
1
我是儿子
const Son = React.memo((props) => { console.log("触发儿子更新"); return <div>我是儿子{props.n}</div>; }); export default class App1 extends React.Component { constructor() { super(); this.state = { n: 1, }; } render() { return ( <> <p>我是爸爸</p> <p>{this.state.n}</p> <button onClick={() => { this.setState({ n: this.state.n + 1 }); }} > +1 </button> <Son /> </> ); } }
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29