Как создать сортируемую таблицу в React? Как получить доступ к методу класса из отсортированных объектов? - PullRequest
2 голосов
/ 06 марта 2019

У меня есть массив объектов. я хочу получить доступ к методу класса внутри свойства функции объекта. Как это реализовать? Помогите мне, пожалуйста. Я написал что-то вроде этого:

render() {       
  tableTh = [
    {name: i18n.t('ExtendedModalBar.naming'), style:{},  handleSort () {}},
      ...
  ]
  ...
}

Я пытаюсь написать что-то вроде этого:

class Table extends Component {

  handleSort() {

  }
  ...

  render() {
  }

}

Заголовки моей таблицы формируются динамически:

<thead>
  <tr>
    <th style={{ width: "50px" }}>
      <Checkbox
        checked={this.state.selectedAll}
        onChange={() => this.selectAll()}
      />
    </th>
    {tableTh.map((obj, index) => {
      return (
        <th key={index.toString()} style={obj.style} onClick={obj.handleSort}>
          {obj.name}
        </th>
      );
    })}
  </tr>
</thead>        

Я должен реализовать сортировку столбцов таблицы. Если таблицы формируются статически, их легко прикрепить к тегу th. но если код был написан так, я застрял. Как написать метод в классе, который будет доступен изнутри свойства объектов (массив объектов)? И мне нужна сортировка в обоих направлениях по возрастанию и убыванию Столбец моей таблицы должен изменить собственное направление сортировки, когда я нажимаю на заголовок таблицы. Любые ответы будут учтены. Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Измените обработчик клика заголовка с onClick={obj.handleSort} на onClick={e => handleSort(columnName, sortDirection). Значения columnName и sortedDirection передаются из родительского компонента

handleSort в Table компонент сможет принимать параметры columnName и sortDirection для манипулирования данными.

Проверьте этот пример реализации

https://codesandbox.io/embed/6lmk0q3w5z?fontsize=14

0 голосов
/ 06 марта 2019

Проблема наличия функции изменения состояния на самом состоянии заключается в том, что это по своей сути затрудняет манипулирование состоянием.

var data = [
  { name: 'a', change: /* ??? */ },
  { name: 'b', change: /* ??? */ },
  { name: 'c', change: /* ??? */ }
]

// How do we write the function ??? to change the order of data?

Гораздо проще поднять логику манипулирования данными на более высокий уровень (вне самих данных).

В этом случае мы бы поместили логику манипулирования данными в сам класс, а не в каждый элемент.

Мы можем сделать это, используя состояние в React.

Состояние используется для хранения любых (динамических) представляемых (отображаемых) данных для компонента. Примером динамических (изменяющихся) презентационных данных может служить таблица, сортирующая столбцы.

Причина, по которой мы хотим перевести презентационные данные в состояние, заключается в том, что React позволяет нам повторно запускать презентацию (путем повторного рендеринга), чтобы всегда показывать самые последние значения для наших данных.

Мы можем достичь этого, просто изменив сами данные, а не какую-либо логику представления. Вот почему структура компонентов React называется декларативной .

Каждый раз, когда состояние обновляется, React вызывает функцию render, чтобы получить структуру компонентов с последними изменениями состояния и отобразить их на соответствующем носителе (в вашем случае DOM )

Вот один из способов включения состояния для создания сортируемой таблицы:

class Table extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      sortDirection: "asc", // we start with ascending order by default
      selectedHeaderIndex: 0 // we start by sorting based on the first header (the one in position 0)
    };

    this.ascComparator = (row1, row2) =>
      row1[this.state.selectedHeaderIndex].localeCompare(
        row2[this.state.selectedHeaderIndex]
      );

    this.descComparator = (row1, row2) =>
      row2[this.state.selectedHeaderIndex].localeCompare(
        row1[this.state.selectedHeaderIndex]
      );

    this.flipSortDirection = () =>
      this.state.sortDirection === "asc" ? "desc" : "asc";
  }

  render() {
    const { headers, rows } = this.props.table;

    const comparator =
      this.state.sortDirection === "asc"
        ? this.ascComparator
        : this.descComparator;

    // sort the rows based on the selected header
    const sortedRows = rows.sort(comparator);

    return (
      <table>
        <thead>
          {headers.map((header, i) => (
            <th
              onClick={() => {
                this.setState({
                  // if we clicked on the already selected index, we flip the sort direction
                  sortDirection:
                    this.state.selectedHeaderIndex === i
                      ? this.flipSortDirection()
                      : "asc",
                  selectedHeaderIndex: i
                });
              }}
            >
              {header}
            </th>
          ))}
        </thead>
        <tbody>
          {sortedRows.map(row => (
            <tr>
              {row.map(cell => (
                <td>{cell}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    );
  }
}

const table = {
  headers: ["h1", "h2", "h3"],
  rows: [["a", "9", "+"], ["b", "6", "-"], ["c", "3", "="]]
};

ReactDOM.render(<Table table={table} />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

При использовании перехватов код становится немного более читабельным ( щелкните для примера CodeSandbox , поскольку SO еще не поддерживает React 16.8):

function Table({ table }) {
  const { headers, rows } = table;

  const [selectedHeaderIndex, setSelectedHeaderIndex] = React.useState(0); // we start by sorting based on the first header (the one in position 0)
  const [sortDirection, setSortDirection] = React.useState("asc"); // we start with ascending order by default

  // determine the sorting comparator based on the sorting direction
  const comparator =
    sortDirection === "asc"
      ? (row1, row2) =>
          row1[selectedHeaderIndex].localeCompare(row2[selectedHeaderIndex])
      : (row1, row2) =>
          row2[selectedHeaderIndex].localeCompare(row1[selectedHeaderIndex]);

  const flipSortDirection = () => (sortDirection === "asc" ? "desc" : "asc");

  // sort the rows based on the selected header
  const sortedRows = rows.sort(comparator);

  return (
    <table>
      <thead>
        {headers.map((header, i) => (
          <th
            onClick={() => {
              setSelectedHeaderIndex(i);
              setSortDirection(
                selectedHeaderIndex === i ? flipSortDirection() : "asc"
              );
            }}
          >
            {header}
          </th>
        ))}
      </thead>
      <tbody>
        {sortedRows.map(row => (
          <tr>
            {row.map(cell => (
              <td>{cell}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}

const table = {
  headers: ["h1", "h2", "h3"],
  rows: [["a", "9", "+"], ["b", "6", "-"], ["c", "3", "="]]
};

ReactDOM.render(<Table table={table} />, document.querySelector("#root"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...