children 相关
class App extends Component {render() {return (<Container><Child/></Container>)}}class Container extends Component {render() {console.log('Container render');return (<div onClick={() => this.setState({})}>{this.props.children}</div>)}}class Child extends Component {render() {console.log('Child render');return <h1>Hi</h1>}}
this.props.children 的写法会将该组件信息置于父组件的对象中,所以当父组件重新渲染时并不会导致其某些对象信息的修改,所以 this.props.children 不会重新渲染。
<Container><Child/></Container>// is equal toReact.createElement(Container,{},React.createElement(Child,{},{}))// which is equal to a React Element object, something like{type: Container,props: {children: {type: Child, // |props: {}, // +---> Take note of this object herechildren: {} // |}}}
组件反复刷新问题排查步骤
检查是否 PureComponent 组件
PureComponent includes by default a shallow comparison of props and state in shouldComponentUpdate, meaning it won’t re-render with the same props and state.
该组件传入的 props 是否一直是新的实例 ```javascript class Child extends PureComponent { render() { return null; } }
class Container extends Component { render() { const filteredList = this.props.list.filter(item => !item.archived);
return (<Childlist={filteredList}onClick={() => console.log('hello')}style={{ padding: '1em' }}/>);
} }
> even if the 3 props passed are not used and hold the same values, each will fail the shallow compare as they will be generated every time Container re-renders: list.filter returns a new Array, and the unnamed inline function and object will have new references.优化手段:```javascriptimport memoize from 'memoize-one';const style = { padding: '1em' };class Child extends PureComponent {render() {return null;}}class Container extends Component {filterList = memoize(() => this.props.list.filter(item => !item.archived));onClick = () => console.log('hello');render() {const filteredList = this.filterList();return (<Childlist={filteredList}onClick={this.onClick}style={style}/>);}}
mapStateToProps 中是否使用了新实例做为返回值,是否有使用 reselect 或 memoizee 等做缓存,避免产生新的实例
const mapStateToProps = () => {const createSideBarLabelGetter = memoize(state => (key) => {const sideBarInfo = [];//...将传入的参数进行操作,而后 memoizee 会通过参数判断是否返回缓存值即可//...memoizee 需要写在 mapStateToProps 中,不然会导致内存泄露return get(sideBarInfo, 'value', '');});return (state) => {return {getSideBarLabel: createSideBarLabelGetter(state),};};};
参考资料
- this.props.children not re-rendered on parent state change
- 为什么我的this.props.children不能re-render?
- React re-rendering, PureComponents and memoization
