Сделайте таблицу React сортированной по алфавиту - PullRequest
1 голос
/ 05 августа 2020

Существует компонент GenericTable, который принимает данные в качестве атрибутов.

в компоненте, который имеет данные:

const headers = ['ID', 'Name', 'City'];
const rows = [{cells: ['1', 'John', 'Paris']},
              {cells: ['3', 'Ben', 'Berlin']},
              {cells: ['2', 'Helen', 'Barcelona']}
              ];
const idList = ['1', '3', '2'];
<GenericTable
  headers={headers}
  rows={rows}
  idList={idList}
/>

в GenericTable:

import { Table } from 'semantic-ui-react';

export default class GenericTable extends React.PureComponent {
  constructor(props) {
    super(props);
  }

  render() {
    const { headers, rows, idList } = this.props;
    
    return (
      <Table>
        <Table.Header>
          <Table.Row>
             {headers.map(header => (
                <Table.HeaderCell key={headers.indexOf(header)}>
                 {header}
                </Table.HeaderCell>
             )}
          </Table.Row>
        </Table.Header>

        <Table.Body>
          {rows.map((row, rowIndex) => (
            <Table.Row key={idList && idList[rowIndex]}>
                <Table.Cell>
                  ...
                </Table.Cell>
         
            </Table.Row>
          )}
        </Table.Body>
      </Table>
    );
  }
}

Есть ли способ сделать таблицу сортированной? Например, добавьте кнопку рядом с заголовком name , и при ее нажатии отсортировать таблицу в алфавитном порядке на основе этого столбца?

Я пытался решить эту проблему, но она не работает. Я добавил значение по умолчанию в состояние, кнопку для каждого заголовка столбца, на которую можно щелкнуть, и при нажатии она должна отсортировать данные на основе этого столбца:

  import { Table } from 'semantic-ui-react';

export default class GenericTable extends React.PureComponent {
  constructor(props) {
    super(props);

    this.state = { // added state
      currentSort: 'default',
    };
  }

onSortChange = () => { // added method
  const { currentSort } = this.state;
  let nextSort;

  if (currentSort === 'down') nextSort = 'up';
  else if (currentSort === 'up') nextSort = 'default';
  else if (currentSort === 'default') nextSort = 'down';

  this.setState({
    currentSort: nextSort,
  });
};

  render() {

    const { currentSort } = this.state; // added state
    const sortTypes = { // added constant
      up: {
       class: 'sort-up',
       fn: (a, b) => a.name - b.name,
      },
      down: {
        class: 'sort-down',
        fn: (a, b) => b.name - a.name,
      },
     default: {
       class: 'sort',
       fn: (a, b) => a,
     },
   };
    const { headers, rows, idList } = this.props;
    
    return (
      <Table>
        <Table.Header>
          <Table.Row>
             {headers.map(header => (
                <Table.HeaderCell key={headers.indexOf(header)}>
                 {header}
                 // added button
                 <button onClick={this.onSortChange} type="button">
                   <i className={`fas fa-${sortTypes[currentSort].class}`} />
                 </button>
                </Table.HeaderCell>
             )}
          </Table.Row>
        </Table.Header>

        <Table.Body>
         // added below
          {[...rows].sort(sortTypes[currentSort].fn).map((row, rowIndex) => (
            <Table.Row key={idList && idList[rowIndex]}>
                <Table.Cell>
                  ...
                </Table.Cell>
         
            </Table.Row>
          )}
        </Table.Body>
      </Table>
    );
  }
}

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Вы можете сохранить опору строк в состоянии компонента. Если щелкнуть заголовок таблицы, вы можете обновить состояние с помощью функции onSortChange

<Table.Row>
      {headers.map((header,index) => (
            <Table.HeaderCell key={headers.indexOf(header)}>
             {header}
             // added below
             <button onClick={() => this.onSortChange(index)} type="button">
          <i className={`fas fa-${sortTypes[currentSort].class}`} />
             </button>
            </Table.HeaderCell>
         )}
</Table.Row>

onSortChange = (i) => { // added method
  var newRows = rows.sort(function(a, b){
    if(a.cells[i] < b.cells[i]) { return -1; }
    if(a.cells[i] > b.cells[i]) { return 1; }
    return 0;
  })
  this.setState({rows: newRows})
};

/ Edit Я сделал здесь пример

https://codesandbox.io/s/nervous-elbakyan-g9tw5?fontsize=14&hidenavigation=1&theme=dark

0 голосов
/ 05 августа 2020

Вот пример того, как можно реализовать сортировку с помощью loda sh. Обратите внимание, что я использую хуки, хотя я вижу, что вы все еще используете классы, но вы все равно можете использовать код в любом случае. Просто нужно использовать состояние компонента вместо хука useReducer. Вы также можете использовать vanilla JS вместо loda sh.

import _ from 'lodash'
import React from 'react'
import { Table } from 'semantic-ui-react'

const headers = ['ID', 'Name', 'City'];

const rows = [{cells: ['1', 'John', 'Paris']},
              {cells: ['3', 'Ben', 'Berlin']},
              {cells: ['2', 'Helen', 'Barcelona']}
              ];

const columnsData = rows.map(row => { 
  return {ID: row.cells[0], Name: row.cells[1], City: row.cells[2] }
})

function tableReducer(state, action) {
  switch (action.type) {
    case 'CHANGE_SORT':
      if (state.column === action.column) {
        return {
          ...state,
          data: state.data.reverse(),
          direction:
            state.direction === 'ascending' ? 'descending' : 'ascending',
        }
      }

      return {
        column: action.column,
        data: _.sortBy(state.data, [action.column]),
        direction: 'ascending',
      }
    default:
      throw new Error()
  }
}


function TableExampleSortable() {
  const [state, dispatch] = React.useReducer(tableReducer, {
    column: null,
    data: columnsData,
    direction: null,
  })
  const { column, data, direction } = state

  return (
    <Table>
        <Table.Header>
          <Table.Row>
             {headers.map(header => (
                <Table.HeaderCell key={headers.indexOf(header)}
                sorted={column === header ? direction : null}
                onClick={() => dispatch({ type: 'CHANGE_SORT', column: header })}>
                 {header}
                </Table.HeaderCell>
             ))}
          </Table.Row>
        </Table.Header>

        <Table.Body>
        {data.map(({ ID, Name, City }) => (
          <Table.Row key={ID}>
            <Table.Cell>{ID}</Table.Cell>
            <Table.Cell>{Name}</Table.Cell>
            <Table.Cell>{City}</Table.Cell>
          </Table.Row>
        ))}
      </Table.Body>

      </Table>
  )
}

export default TableExampleSortable
...