Constructing state object for all the columns of a

2019-08-23 07:41发布

问题:

Need to construct a state object that will be helpful for maintaining fieldname and type of sort(ascending/descending).

I am trying to implement sorting where the sorting on the server side happens by taking the column name and the type of sort(asc or des).

I am maintaining a component for a data table where-in I attach a click handler that basically should give the field name that I click and the type of sorting. I can hardcode the fieldnam, But how will I map each column with type of sorting.

I just need the name of the field and type to be sent to the backend, then it will give me sorted results. How will I map corresponding column names with either asc/desc

Can someone help me with this?

Sandbox: https://codesandbox.io/s/misty-water-iutxl

import * as React from "react";
import ReactTable from "react-table";
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: any) {
    super(props);
    this.state = {
      data: [],
      columns: [],
    };
  }

  componentDidMount()
  {
    this.getColumnFilterValues();
    this.getData();
  }

  getData = () =>{
    let data = [
        { firstName: "Jack", status: "Submitted", age: "14" },
        { firstName: "Simon", status: "Pending", age: "15" },
        { firstName: "Pete", status: "Approved", age: "17" }
      ];
      this.setState({data},()=> this.getColumns());
  }

  getColumnFilterValues = () =>{
    let optionsForColumns = {
        firstName: [
          { Jack: "4", checked: false },
          { Simon: "5", checked: false },
          { Pete: "10", checked: false }
        ],
        status: [
          { Submitted: "5", checked: false },
          { Pending: "7", checked: false },
          { Approved: "15", checked: false }
        ]
      }
      this.setState({optionsForColumns});
  }

  sortHandler = (name) =>{
     //Sort Handler, here I have to pass the field name and type of sorting
  }

  getColumns = () =>{
    let columns = [
      {
        Header: () => (
          <div>
            <div style={{ position: "absolute", marginLeft: "10px" }}>
              <Child
                key="firstName"
                name="firstName"
                options={this.getValuesFromKey("firstName")}
                handleFilter={this.handleFilter}
              />
            </div>
            <span onClick={()=>this.sortHandler("firstName")}>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("status")}
                handleFilter={this.handleFilter}
              />
            </div>
            <span onClick={()=>this.sortHandler("status")}>Status</span>
          </div>
        ),
        accessor: "status",
        sortable: false
      },
      {
        Header: () =>(
          <span onClick={this.sort}>Age</span>
        ),
        accessor: "age"
      }
    ];
    this.setState({ columns });
  }

  //Rendering the data table
  render() {
    const { data, columns } = this.state;
    return (
      <div>
        <ReactTable
          data={data}
          columns={columns}
        />
      </div>
    );
  }
}


回答1:

The sorting type will be just an inversion of the current sorting type. So you would need to keep track each column sorting type. After that, you can do something like;

// imagine sortingTypes are stored in the state like so:
state = {
  sortingTypes: {
    firstName: 'ASC',
    lastName: '',
  },
};


// in the onClick handler
sortHandler = (name) =>{
  //Sort Handler, here I have to pass the field name and type of sorting

  // Make a new sortingTypes object
  const sortingTypes = Object.keys(this.state.sortingTypes).reduce((obj, key) => {
    if (key === name) {
      obj[key] = sortingTypes[key] === 'ASC' ? 'DESC' : 'ASC';
    } else {
      obj[key] = '';
    }

    return obj;
  }, {});

  // calling this.getColumns() in the setState callback function is not recommended. 
  // The getColumns function is also calling setState and caused the component to update 
  // twice while that is not needed.
  this.setState({ sortingTypes }, () => this.getColumns());
}

edit

After looking into react-table, I've realised that you don't have to manage the state yourself. Just set the manual and onFetchData prop and you know exactly when to fetch your data and with which sorting options;

<ReactTable
  data={data}
  columns={columns}
  defaultPageSize={10}
  loading={this.state.loading}
  className="-striped -highlight"
  onFetchData={(({ sorted }) => {
    // here you can fetch data with the table state like `sorting`.
    console.log(sorted && sorted[0] && sorted[0].id);
  })}
  manual
/>

See the Server-side data chapter in the React Table documentation for more information.