首页 > 解决方案 > 在不渲染父组件 React js 的情况下重新渲染子组件

问题描述

我正在学习 React js。我需要从父组件重新渲染其中一个子组件。一种方法是我可以将 setState 用于矩阵,但作为父组件的整个矩阵将被重新渲染,而我只想重新渲染一个子组件。这已通过下面的代码添加。

Child.js

import React from 'react';

class Child extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            text : ""
        };
    }

    updateParent(text) {
        if(text) {
            this.setState({text : text});
        }
    }

    render() {
        return(
            <div>Child {this.state.text}</div>
        );
    }
}

export default Child;

父.js

import React from 'react';
import Child from './Child'

class Parent extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            table : [[<Child key={11}/>, <Child key={12}/>, <Child key={13}/>],
                     [<Child key={21}/>, <Child key={22}/>, <Child key={23}/>]],
            i : 0,
            j : 0
        };
    }

    componentDidMount() {
        this.timerID1 = setInterval(() => this.updateTable(), 1000);
    }

    updateTable() {
        //this.state.table[this.state.i][this.state.j].updateParent("");
        this.state.j++;
        if( this.state.j % 3 == 0) {
            this.state.i++;
            this.state.i %= 2;
        }
        //this.state.table[this.state.i][this.state.j].updateParent("*");
        // or tempTable[i][j] = <Child key={ij} text={"*"}/>; this.setState({table: tempTable});
        this.state.j++;
    }

    createTable() {
        let table = []
        for(let i = 0; i < 2; i++) {
            table.push( <div key={i} style={{display:"flex"}}>{this.state.table[0]}</div> )
        }
        return table;
    }

    render() {
        return(
            <div>{this.createTable()}</div>
        );
    }
}
export default Parent;

标签: reactjs

解决方案


  • 不要将子组件实例存储在状态中,而是动态渲染它们

  • 您可以将 Child 实现为 PureComponent ,这样如果它没有任何道具或状态更改,它就不会重新渲染

  • 不要像你一样直接改变状态this.state.j++等等。使用 setState

父.js

export default class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      table: this.createTableData(3),
      i: 0,
      j: 0
    };
  }

  createTableData(size) {
    const arr = new Array(size);
    for (var i = 0; i < size; i++) {
      arr[i] = new Array(size).fill("");
    }
    return arr;
  }
  componentDidMount() {
    this.timerID1 = setInterval(() => this.updateTable(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timerID1);
  }
  updateTable() {
    let { i, j, table } = this.state;
    j++;
    if (j % 3 == 0) {
      i++;
      i %= 2;
    }
    const newTable = table.map((tr, row) => {
      return tr.map((td, col) => {
        if (row == i && col == j) {
          return "*";
        } else {
          return "";
        }
      });
    });
    j++;
    this.setState({
      table: newTable,
      i,
      j
    });
  }

  createTable() {
    return this.state.table.map((row, i) => {
      return (
        <div className="row">
          {row.map((col, j) => {
            return <Child key={`${i + 1}${j + 1}`} text={col} />;
          })}
        </div>
      );
    });
  }

  render() {
    return <div>{this.createTable()}</div>;
  }
}

Child.js

class Child extends React.PureComponent {
  render() {
    console.log("child rerender", this.props.text);
    return <div>Child {this.props.text} &nbsp;</div>;
  }
}

工作演示

注意: demo 仅包含显示和性能优化逻辑以及架构,更新索引 i、j 的逻辑需要您在 updateTable 方法中完成。

如果你看演示,只有你的值从“”变为“*”的单元格会重新渲染,其余的不会


推荐阅读