memorization

memorization 技术(仅在输入变化时,重新计算 render 需要使用的值)

可以优化 React 组件的性能

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 不太好的方法(因为太复杂):派生 state 作为缓存
class Example extends Component {
state = {
filterText: "",
};

static getDerivedStateFromProps(props, state) {
// 列表变化或者过滤文本变化时都重新过滤。
// 注意我们要存储 prevFilterText 和 prevPropsList 来检测变化。
if (
props.list !== state.prevPropsList ||
state.prevFilterText !== state.filterText
) {
return {
prevPropsList: props.list,
prevFilterText: state.filterText,
filteredList: props.list.filter(item => item.text.includes(state.filterText))
};
}
return null;
}

handleChange = event => {
this.setState({ filterText: event.target.value });
};

render() {
return (
<Fragment>
<input onChange={this.handleChange} value={this.state.filterText} />
<ul>{this.state.filteredList.map(item => <li key={item.id}>{item.text}</li>)}</ul>
</Fragment>
);
}
}

// pureComponent 来简化
class Example extends PureComponent {
// state 只需要保存 filter 的值:
state = {
filterText: ""
};

handleChange = event => {
this.setState({ filterText: event.target.value });
};

render() {
// PureComponent 的 render 只有
// 在 props.list 或 state.filterText 变化时才会调用
const filteredList = this.props.list.filter(
item => item.text.includes(this.state.filterText)
)

return (
<Fragment>
<input onChange={this.handleChange} value={this.state.filterText} />
<ul>{filteredList.map(item => <li key={item.id}>{item.text}</li>)}</ul>
</Fragment>
);
}
}
// 当有 prop 改变时 PureComponent 不会阻止再次渲染。

// 引入memorization函数来阻止非必要的过滤
// 我们会限制 memoization 帮助函数的缓存空间,以免内存泄漏。使用 memoize-one 只缓存最后一次的参数和结果。
import memoize from "memoize-one";

class Example extends Component {
// state 只需要保存当前的 filter 值:
state = { filterText: "" };

// 在 list 或者 filter 变化时,重新运行 filter:
filter = memoize(
(list, filterText) => list.filter(item => item.text.includes(filterText))
);

handleChange = event => {
this.setState({ filterText: event.target.value });
};

render() {
// 计算最新的过滤后的 list。
// 如果和上次 render 参数一样,`memoize-one` 会重复使用上一次的值。
const filteredList = this.filter(this.props.list, this.state.filterText);

return (
<Fragment>
<input onChange={this.handleChange} value={this.state.filterText} />
<ul>{filteredList.map(item => <li key={item.id}>{item.text}</li>)}</ul>
</Fragment>
);
}
}
-------------要说再见啦感谢大佬的光临~-------------