正确更新 React 状态

Update React state correctly

如何正确更新反应状态?我有一个国家/地区下拉列表和一个 table 国家/地区及其城市。根据从下拉列表中选择的国家/地区,table 应仅显示该国家/地区和城市。

下面的代码第一次正确地过滤了 table 数据。更改国家/地区后,table 不会显示所选国家/地区从 开始的数据。

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";

import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";

import MenuItem from "@material-ui/core/MenuItem";
import Select from "@material-ui/core/Select";

import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";

const useStyles = makeStyles(theme => ({
  button: {
    margin: theme.spacing(1)
  },
  input: {
    display: "none"
  }
}));

class App extends Component {
  state = {
    selectedCountry: "",
    countries: []
  };

  constructor() {
    super();

    this.state.countries = [
      this.createData("US", "DC"),
      this.createData("UK", "London"),
      this.createData("Aus", "Canberra"),
      this.createData("US", "Newyork"),
      this.createData("UK", "Birmingham"),
      this.createData("Aus", "Sidney")
    ];
  }

  createData(country, capital) {
    return { country, capital };
  }

  handleChange(value) {
    this.setState({ selected: value });
    this.setState({
      countries: this.state.countries.filter(c => c.country === value)
    });
  }

  render() {
    return (
      <div className="App">
        <label value="Select Country: ">Select Country: </label>
        <Select
          style={{ width: "10%" }}
          value={this.state.selected}
          onChange={event => this.handleChange(event.target.value)}
          name="country"
          displayEmpty
        >
          <MenuItem value="" disabled>
            Select a country
          </MenuItem>
          <MenuItem value="US">US</MenuItem>
          <MenuItem value="UK">UK</MenuItem>
          <MenuItem value="AUS">Aus</MenuItem>
        </Select>

        <Table>
          <TableHead>
            <TableRow>
              <TableCell align="center">Country</TableCell>
              <TableCell align="center">Capital city</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {this.state.countries.map(row => (
              <TableRow key={row.name}>
                <TableCell align="center">{row.country}</TableCell>
                <TableCell align="center">{row.capital}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
    );
  }
}

export default App;

问题就在这里,

this.setState({
   countries: this.state.countries.filter(c => c.country === value)
});

此处您过滤 countries 数组并将其存储到相同的数组中。因此,当您第一次过滤时,原始 countries 数组会发生变化,您只有过滤后的数据。在下一个过滤器中,您将过滤来自先前结果而不是原始数组的数据。

您需要在构造函数中保留原始数据的副本,

constructor() {
    super();
    //This is initial state
    this.state.countries = [
      this.createData("US", "DC"),
      this.createData("UK", "London"),
      this.createData("Aus", "Canberra"),
      this.createData("US", "Newyork"),
      this.createData("UK", "Birmingham"),
      this.createData("Aus", "Sidney")
    ];

    //this is the copy of original data
    this.countries = [
      this.createData("US", "DC"),
      this.createData("UK", "London"),
      this.createData("Aus", "Canberra"),
      this.createData("US", "Newyork"),
      this.createData("UK", "Birmingham"),
      this.createData("Aus", "Sidney")
    ];
  }

现在每次都可以过滤原始数据,

this.setState({
   countries: this.countries.filter(c => c.country === value)
});

Demo

注意:在你的filter中进行比较时,你应该使用.toLowerCase()。因为您所在州的国家/地区为 Aus,select 中的值为 AUS。比较小写值更好,

this.setState({
   countries: this.countries.filter(c => c.country.toLowerCase() === value.toLowerCase())
});

在 render 方法中使用 const 值。当所选国家/地区发生变化时,const 值将每次更新。

删除行 this.setState({ countries: this.state.countries.filter(c => c.country === value) });

并添加以下代码

render() {
    const filteredCountries = this.state.countries.filter(c=> c.countries === this.state.selected);
    return (
      <div className="App">
        <label value="Select Country: ">Select Country: </label>
        <Select
          style={{ width: "10%" }}
          value={this.state.selected}
          onChange={event => this.handleChange(event.target.value)}
          name="country"
          displayEmpty
        >
          <MenuItem value="" disabled>
            Select a country
          </MenuItem>
          <MenuItem value="US">US</MenuItem>
          <MenuItem value="UK">UK</MenuItem>
          <MenuItem value="AUS">Aus</MenuItem>
        </Select>

        <Table>
          <TableHead>
            <TableRow>
              <TableCell align="center">Country</TableCell>
              <TableCell align="center">Capital city</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {this.state.filteredCountries.map(row => (
              <TableRow key={row.name}>
                <TableCell align="center">{row.country}</TableCell>
                <TableCell align="center">{row.capital}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
    );
  }

与使用另一个状态 "filteredCountries" 相比,这是解决此问题的更有效方法。