children 相关

  1. class App extends Component {
  2. render() {
  3. return (
  4. <Container>
  5. <Child/>
  6. </Container>
  7. )
  8. }
  9. }
  10. class Container extends Component {
  11. render() {
  12. console.log('Container render');
  13. return (
  14. <div onClick={() => this.setState({})}>
  15. {this.props.children}
  16. </div>
  17. )
  18. }
  19. }
  20. class Child extends Component {
  21. render() {
  22. console.log('Child render');
  23. return <h1>Hi</h1>
  24. }
  25. }

this.props.children 的写法会将该组件信息置于父组件的对象中,所以当父组件重新渲染时并不会导致其某些对象信息的修改,所以 this.props.children 不会重新渲染。

  1. <Container>
  2. <Child/>
  3. </Container>
  4. // is equal to
  5. React.createElement(
  6. Container,
  7. {},
  8. React.createElement(
  9. Child,
  10. {},
  11. {}
  12. )
  13. )
  14. // which is equal to a React Element object, something like
  15. {
  16. type: Container,
  17. props: {
  18. children: {
  19. type: Child, // |
  20. props: {}, // +---> Take note of this object here
  21. children: {} // |
  22. }
  23. }
  24. }

组件反复刷新问题排查步骤

  1. 检查是否 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.

  2. 该组件传入的 props 是否一直是新的实例 ```javascript class Child extends PureComponent { render() { return null; } }

class Container extends Component { render() { const filteredList = this.props.list.filter(item => !item.archived);

  1. return (
  2. <Child
  3. list={filteredList}
  4. onClick={() => console.log('hello')}
  5. style={{ padding: '1em' }}
  6. />
  7. );

} }

  1. > 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.
  2. 优化手段:
  3. ```javascript
  4. import memoize from 'memoize-one';
  5. const style = { padding: '1em' };
  6. class Child extends PureComponent {
  7. render() {
  8. return null;
  9. }
  10. }
  11. class Container extends Component {
  12. filterList = memoize(() => this.props.list.filter(item => !item.archived));
  13. onClick = () => console.log('hello');
  14. render() {
  15. const filteredList = this.filterList();
  16. return (
  17. <Child
  18. list={filteredList}
  19. onClick={this.onClick}
  20. style={style}
  21. />
  22. );
  23. }
  24. }
  1. mapStateToProps 中是否使用了新实例做为返回值,是否有使用 reselect 或 memoizee 等做缓存,避免产生新的实例

    1. const mapStateToProps = () => {
    2. const createSideBarLabelGetter = memoize(state => (key) => {
    3. const sideBarInfo = [];
    4. //...将传入的参数进行操作,而后 memoizee 会通过参数判断是否返回缓存值即可
    5. //...memoizee 需要写在 mapStateToProps 中,不然会导致内存泄露
    6. return get(sideBarInfo, 'value', '');
    7. });
    8. return (state) => {
    9. return {
    10. getSideBarLabel: createSideBarLabelGetter(state),
    11. };
    12. };
    13. };

    参考资料

  2. 深入理解 react/redux 数据流并基于其优化前端性能

  3. this.props.children not re-rendered on parent state change
  4. 为什么我的this.props.children不能re-render?
  5. React re-rendering, PureComponents and memoization