避免在父组件状态更改后将孩子的状态设置为初始值:ReactJS + Typescript

时间:2019-07-25 06:10:21

标签: javascript reactjs setstate semantic-ui-react react-table

我对反应有点陌生,在这种情况下,我为React中的表实现自定义下拉过滤器。我为每列设置了下拉值,并且有一个“应用”按钮。

为此,我维护了一个子组件,该组件接收下拉值并将选定的组件返回给父组件。然后,我调用一个后端API,该API向我提供过滤后的数据,这些数据依次设置了父状态。问题是我获取数据并设置父状态后,下拉列表中的复选框值丢失了。

我不明白为什么我会丢失复选框值?

如果有人可以帮助我,这将有很大帮助

我正在做类似的事情:代码沙箱:https://codesandbox.io/s/quizzical-glitter-np8iw

主要组件

import * as React from "react";
import { render } from "react-dom";
import ReactTable from "react-table";
import "./styles.css";
import "react-table/react-table.css";
import Child from "./Child";
interface IState {
  data: {}[];
  columns: {}[];
  selectedValues: {};
}

interface IProps {}

export default class App extends React.Component<IProps, IState> {
  constructor(props) {
    super(props);
    this.state = {
      data: [
        { firstName: "Jack", status: "Submitted", age: "14" },
        { firstName: "Simon", status: "Pending", age: "15" },
        { firstName: "Pete", status: "Approved", age: "16" },
        { firstName: "Lucas", status: "Rejected", age: "19" }
      ],
      selectedValues: {},
      columns: []
    };
  }

  getValuesFromKey = (data, key) => {
    return data.map(item => item[key]);
  };

  handleFilter = (fieldName: any, selectedValue: any) => {
    this.setState(
      {
        selectedValues: {
          ...this.state.selectedValues,
          [fieldName]: selectedValue
        }
      },
      () => this.handleColumnFilter(this.state.selectedValues)
    );
  };

  handleColumnFilter = (values: any) => {
    //  Here I make a backend API call that gives me filtered data and then I set the tables data.
    // this.setState({data: filteredDataFromServer});
    // I lose the checkbox values here
  };

  componentDidMount() {
    let columns = [
      {
        Header: () => (
          <div>
            <div style={{ position: "absolute", marginLeft: "10px" }}>
              <Child
                key="firstName"
                name="firstName"
                options={this.getValuesFromKey(this.state.data, "firstName")}
                handleFilter={this.handleFilter}
              />
            </div>
            <span>First Name</span>
          </div>
        ),
        accessor: "firstName",
        sortable: false,
        show: true,
        displayValue: " First Name"
      },
      {
        Header: () => (
          <div>
            <div style={{ position: "absolute", marginLeft: "10px" }}>
              <Child
                key="status"
                name="status"
                options={this.getValuesFromKey(this.state.data, "status")}
                handleFilter={this.handleFilter}
              />
            </div>
            <span>Status</span>
          </div>
        ),
        accessor: "status",
        sortable: false
      },
      {
        Header: "Age",
        accessor: "age"
      }
    ];
    this.setState({ columns });
  }

  render() {
    const { data, columns } = this.state;
    return (
      <div>
        <ReactTable
          data={data}
          columns={columns}
          defaultPageSize={10}
          className="-striped -highlight"
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);



子组件


import * as React from "react";
import { Button, Checkbox, Icon } from "semantic-ui-react";
import "./styles.css";
interface IProps {
  options: any;
  name: string;
  handleFilter(val1: any, val2: any): void;
}
interface IState {
  showList: boolean;
  selected: [];
}
export default class Child extends React.Component<IProps, IState> {
  constructor(props) {
    super(props);
    this.state = {
      selected: [],
      showList: false
    };
  }

  handleValueChange = (event: React.FormEvent<HTMLInputElement>, data: any) => {
    let updated: any;
    if (data.checked) {
      updated = [...this.state.selected, data.name];
    } else {
      updated = this.state.selected.filter(v => v !== data.name);
    }
    this.setState({ selected: updated });
  };

  passSelectionToParent = (event: any) => {
    event.preventDefault();
    // I am sending the selected column name and corresponding checked values to parent
    this.props.handleFilter(this.props.name, this.state.selected);
  };

  toggleList = () => {
    this.setState(prevState => ({ showList: !prevState.showList }));
  };

  render() {
    let { showList } = this.state;
    let visibleFlag: string;
    if (showList === true) visibleFlag = "visible";
    else visibleFlag = "";
    return (
      <div>
        <div style={{ position: "absolute" }}>
          <div
            className={"ui scrolling dropdown column-settings " + visibleFlag}
          >
            <Icon className="filter" onClick={this.toggleList} />
            <div className={"menu transition " + visibleFlag}>
              <div className="menu-item-holder">
                {this.props.options.map((item: any, i: number) => (
                  <div className="menu-item" key={i}>
                    <Checkbox
                      name={item}
                      onChange={this.handleValueChange}
                      label={item}
                    />
                  </div>
                ))}
              </div>
              <div className="menu-btn-holder">
                <Button size="small" onClick={this.passSelectionToParent}>
                  Apply
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}


0 个答案:

没有答案