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 to
React.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 here
children: {} // |
}
}
}
组件反复刷新问题排查步骤
检查是否 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 (
<Child
list={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.
优化手段:
```javascript
import 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 (
<Child
list={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