正确更新React状态

时间:2019-09-15 04:34:21

标签: reactjs material-ui react-state

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

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

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;

2 个答案:

答案 0 :(得分:0)

问题出在这里

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

注意:在比较.toLowerCase()时,应使用filter。因为您在自己的州拥有Aus作为国家/地区,在您的选择中拥有AUS作为价值。最好比较一下lowerCase值,

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

答案 1 :(得分:0)

在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”的另一个状态,而是解决此问题的更有效方法。