memorization-根据输入重新计算render的数据
在实际开发过程中,经常遇到根据props和state变化,重新计算“渲染阶段”需要的数据的情况。
如:根据输入的值实时过滤select列表,或者表格数据(查询过滤)。
问题特点:
1. 每次渲染都会调用相关操作
2. 进行的操作都是和渲染相关的,如根据参数计算渲染需要的数据
常用方法:
1)在getDerivedStateFromProps()中判断涉及的属性变化,来更新数据。
这种方法在涉及属性较多时,特别复杂。
2)在render()方法中计算数据,并且使用PureComponent。
这种方法只要render就会计算,即使其他无关属性,也会导致重新渲染,从而触发计算。
特别是数据较大时,特别影响性能。
memoization技术
memoization函数可以解决上面两个方法的弊端。
“memoize-one”只缓存最后一次的结果,不会触发内存泄漏。
示例代码:
import React, {PureComponent} from 'react'; import ReactDOM from 'react-dom'; import memoize from 'memoize-one'; class App extends PureComponent { constructor(props) { super(props); this.state = { list: [] } this.inputRef = React.createRef(); } add = () => { this.setState(state => ({ list: state.list.concat(this.inputRef.current.value) })) } render() { return ( <div> <Child list={this.state.list} /> <br/> <input defaultValue="" ref={this.inputRef} /> <button onClick={this.add}>ClikeMe Add</button> </div> ) } } class Child extends React.Component { state = { filterText: null } // memoize-one可以缓存最后一次的数据和结果;避免内存泄漏 // 否则在getDerivedStateFromProps中需要比较list前后的值和filterText前后的值 // 来避免重复计算 filter = memoize( (list, filterText) => list.filter(i => i.includes(filterText)) ) handleChange = (e) => { this.setState({ filterText: e.target.value }) } render() { const filterList = this.filter(this.props.list, this.state.filterText) return ( <form> <fieldset> <legend>过滤参数</legend> <input onChange={this.handleChange}/> </fieldset> { filterList && filterList.map((i,index) => ( <div key={i}>{index}---{i}</div> )) } </form> ) } } ReactDOM.render(<App/>, window.root)