渲染子对象而不渲染父组件React js

时间:2020-05-04 11:42:01

标签: reactjs

我正在学习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;

Parent.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;

2 个答案:

答案 0 :(得分:2)

  • 不要在状态下存储子组件实例,而是动态呈现它们

  • 您可以将Child实现为PureComponent,这样,如果没有props或状态更改,它就不会重新呈现

  • 不要像this.state.j++那样直接改变状态,依此类推。使用setState

Parent.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>;
  }
}

working demo

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

如果您观看演示,则只会重新渲染其值从“”更改为“ *”,反之亦然的单元格,其余单元格不会重新显示

答案 1 :(得分:0)

您可以在不渲染父组件的情况下重新渲染子组件

使用 ref 从父级调用子级功能并更新子级组件

Parent.js

import React from "react";
import Table from "./Table";
import Child from "./Child";

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

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

  updateTable() {
    this.j++;
    if (this.j % 3 == 0) {
      this.i++;
      this.i %= 2;
    }
    this.j++;
    this.table[0].push(
      <Child key={21} />,
      <Child key={22} />,
      <Child key={23} />
    );
    this.refs.table.updateTable(this.table[0]);
  }

  componentDidUpdate() {
    console.log("component rerender");
  }

  render() {
    return (
      <div>
        <h1>Parent Component</h1>
        <Table ref="table" />
      </div>
    );
  }
}
export default Parent;

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;

Table.js

import React, { Component } from "react";

class table extends Component {
  state = {
    table: [],
  };

  updateTable = (table) => {
    this.setState({ table });
  };
  render() {
    const { table } = this.state;
    return (
      <div>
        {table.map((tableItem, i) => {
          return <div key={i} style={{ display: "flex" }}>{tableItem}</div>;
        })}
      </div>
    );
  }
}

export default table;

如果重新渲染,

componentDidUpdate 将提供日志

注意:我未在父组件中使用状态。如果要使用父组件状态,则必须使用 shouldComponentUpdate 生命周期

停止重新渲染