ReactJS - 如何正确呈现源自父组件并传递给子组件的内容?

ReactJS - How can I properly render content that originates in a parent component and is passed down to a child component?

当字符串顺序数组作为 prop 传递给此组件时,我似乎无法在 CarTable.tsx 中呈现我的列名称。我知道这是一些古怪的异步编程。此外,当我单击该按钮时,列名的顺序应该会发生变化,并且这种变化应该会反映在重新呈现中。

我无法理解它。我认为诸如 setState() 之类的异步内容应该放在诸如 ComponentDidMount() 之类的生命周期钩子中(同事建议)。

此外,当父组件 (App.tsx) 更改状态并且此状态作为 prop 传递给子组件 (CarTable.tsx) 时,CarTable 不应该通过虚拟重新渲染DOM 检测到变化?

我试过使用 ComponentDidMount() 和 ComponentWillMount() 来设置状态。

App组件代码如下

import React from 'react';
import './App.css';
import { Car } from './Models/Car';
import CarTable from './CarTable';

class App extends React.Component<any, any> {

  constructor(props: any) {
    super(props);

    this.state = {
      cars: [],
      ordering: []
    }

    this.changeColumnOrder = this.changeColumnOrder.bind(this);
  }

  componentDidMount() {
    let order = [
      ["Model", "Make", "Year"], ["Model", "Year", "Make"], 
      ["Make", "Model", "Year"], ["Make", "Year", "Model"], 
      ["Year", "Model", "Make"], ["Year", "Make", "Model"]
    ];

    let random = Math.floor(Math.random() * 5); // 0 - 5

    var models: string[] = ["Accord", "Civic", "Pathfinder"];
    var make: string = "Honda";
    var years: number[] = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019];

    var cars: Car[] = [];

    for (let i = 0; i < 40; i++) {
      var randYear = Math.floor(Math.random() * 10); // 0 - 9
      var randModel = Math.floor(Math.random() * 3); // 0 - 2
      cars.push(new Car(models[randModel], make, years[randYear]));
    }

    console.log("Cars generated...");
    console.log(cars);

    this.setState({
      cars: cars,
      ordering: order[random]
    });
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1>Car Table</h1>
          <button onClick={this.changeColumnOrder} className="columnButton">Change Column Order</button>
          <CarTable cars={this.state.cars} order={this.state.ordering}></CarTable>
        </header>
      </div>
    );
  }

  // Method for changing the column order of the contents in the car table. 
  changeColumnOrder() {

    let order = [
      ["Model", "Make", "Year"], ["Model", "Year", "Make"], 
      ["Make", "Model", "Year"], ["Make", "Year", "Model"], 
      ["Year", "Model", "Make"], ["Year", "Make", "Model"]
    ];

    let random = Math.floor(Math.random() * 5); // 0 - 5

    console.log("Testing random order");
    console.log(order[random]);

    this.setState({
      ordering: order
    });

    console.log("Testing after set state.");
    console.log(order[random]);
    this.forceUpdate();
  }
}

export default App;

这是 CarTable 组件代码。

import React from 'react';
import './App.css';
import { Car } from './Models/Car';

export default class CarTable extends React.Component<any, any> {

    constructor(props: any) {
        super(props);

        this.state = {
            cars: [],
            columnOrder: []
        }
    }

    componentWillMount(){
        this.setState({
            cars: this.props.cars,
            columnOrder: this.props.order
        });

        console.log("In CarTable.tsx, component did mount");
        console.log(this.state.columnOrder);
    }

    render() {
        return(
            <table id="carsTable">
                <thead>
                    <tr>
                    {this.state.columnOrder.map((column: string, key: any) => {
                        console.log("in header...")
                        console.log({column});
                        return(<th key={column}>{column}</th>)
                    })}
                    </tr>
                </thead>
                <tbody>
                    {this.state.cars.map((car: Car, key: any) => {
                        return(
                            <tr key={key}>
                                <td key={car.Make}>{car.Make}</td>
                                <td key={car.Model}>{car.Model}</td>
                                <td key={car.Year}>{car.Year}</td>
                            </tr>
                        )
                    })}
                </tbody>
            </table>
        )
    }
}

使用当前状态下的代码,我根本无法呈现我的列名(型号、汽车、年份)。

在 CarTable 构造函数中,删除

this.setState({
    cars: this.props.cars,
    columnOrder: this.props.order
});

在渲染中,使用 this.props.cars 和 columnOrder 而不是 this.state.xxx

就是这样

实际上,您可以删除 CarTable.constructorCarTable.componentWillMount。 也去掉父组件this.forceUpdate();中的

你做错了,你不需要子组件中的状态。只需按原样使用道具值

import React from 'react';
import './App.css';
import { Car } from './Models/Car';

export default class CarTable extends React.Component<any, any> {
    render() {
        return(
            <table id="carsTable">
                <thead>
                    <tr>
                    {this.props.order.map((column: string, key: any) => {
                        console.log("in header...")
                        console.log({column});
                        return(<th key={column}>{column}</th>)
                    })}
                    </tr>
                </thead>
                <tbody>
                    {this.props.cars.map((car: Car, key: any) => {
                        return(
                            <tr key={key}>
                                <td key={car.Make}>{car.Make}</td>
                                <td key={car.Model}>{car.Model}</td>
                                <td key={car.Year}>{car.Year}</td>
                            </tr>
                        )
                    })}
                </tbody>
            </table>
        )
    }
}