title: React table with sorting and pagination doesn't update
body: <p>I am making a simple table in react where I have pagination (separate component) and sorting.</p>
  
  <p>The table should sort update when table header is clicked. It changes state of data. The data is sorted but it doesn't update. The table is rerendered when I change page (pagination component) and it does have sorted data. 
  The problem is with </p>
  
  <pre><code> this.state.pageOfItems.map((element, index) =&gt;
  </code></pre>
  
  <p>if I change it to </p>
  
  <pre><code> this.state.data.map((element, index) =&gt;
  </code></pre>
  
  <p>then sorting works, but pagination doesn't</p>
  
  <p>Please help me get the table data updated immidiately when table header is clicked.</p>
  
  <p><strong>Table component:</strong></p>
  
  <pre><code>    import React, { Component } from 'react';
  
      import classes from './Table.css';
      import data from 'data.json';
      import Pagination from '../Pagination/Pagination';
  
      class Table extends Component {
      constructor(props){
        super(props);
        this.state = {
          data: props.data,
          headings: Object.keys(props.data[0]),
          sortOrder: props.sortOrder || "original",
          sortKey: props.sortKey || null,
          pageOfItems: []
        };
        this.sortHandler = this.sortHandler.bind(this);
        this.onChangePage = this.onChangePage.bind(this);
  
      }
  
      componentWillMount() {
        //TODO: only apply this to the root element of the table component
        document.addEventListener('dragover', (event) =&gt; {
          event.preventDefault();
        });
      }
  
      sortHandler(e){
        const sortKey = e.target.dataset.sortcolumn;
        const currentSortKey = this.state.sortKey;
        const currentSortOrder = (sortKey === currentSortKey) ? this.state.sortOrder : "original";
        this.setState({sortKey: e.target.dataset.sortcolumn});
        console.log(currentSortOrder)
        switch(currentSortOrder){
          case "original":
          this.setState({sortOrder: "ascending"});
          this.state.data.sort((a, b)=&gt;{
            if (a[sortKey] &lt; b[sortKey]) {
              return -1;
            }
            if (a[sortKey] &gt; b[sortKey]) {
              return 1;
            }
            return 0;
          });
          break;
          case "ascending":
          this.setState({sortOrder: "descending"});
          this.state.data.sort((a, b)=&gt;{
            if (a[sortKey] &lt; b[sortKey]) {
              return 1;
            }
            if (a[sortKey] &gt; b[sortKey]) {
              return -1;
            }
            return 0;
          });
          break;
          case "descending":
          this.setState({sortOrder: "original"});
          this.state.data = this.props.data;
          break;
        }
        this.setState({data: this.state.data});
        console.log(this.state.data);
      }
  
      onChangePage(pageOfItems) {
        // update state with new page of items
        this.setState({ pageOfItems: pageOfItems });
      }
  
      render() {
        return (
          &lt;div role="region" aria-labelledby={this.props.id} tabindex="0" style={{overflow: 'auto'}}&gt;
          &lt;table cellSpacing="0" cellPadding="0" data-sortorder={this.state.sortOrder}&gt;
          {this.props.caption &amp;&amp;
            &lt;caption id={this.props.id}&gt;{this.props.caption}&lt;/caption&gt;
          }
          &lt;thead&gt;
          &lt;tr&gt;
          {this.state.headings.map((element, index) =&gt; {
            return (
              &lt;th
              data-sortcolumn={element}
              id={'header' + index}
              onClick={this.sortHandler}&gt;
              {element}
              &lt;/th&gt;
            )
          })}
          &lt;/tr&gt;
          &lt;/thead&gt;
          &lt;tbody&gt;
          {this.state.pageOfItems.map((element, index) =&gt; {
            return (
              &lt;tr
              id={'row' + index}&gt;
              {element &amp;&amp; Object.values(element).map((cell)=&gt;{
                return &lt;td&gt;
                {cell}
                &lt;/td&gt;
              })}
              &lt;/tr&gt;
            )
          })}
          &lt;/tbody&gt;
          &lt;/table&gt;
          &lt;Pagination items={this.state.data} onChangePage={this.onChangePage} /&gt;
          &lt;/div&gt;
        );
      }
    }
  </code></pre>
  
  <p><strong>Pagination component:</strong> </p>
  
  <pre><code>import React from 'react';
  import PropTypes from 'prop-types';
  
  const propTypes = {
      items: PropTypes.array.isRequired,
      onChangePage: PropTypes.func.isRequired,
      initialPage: PropTypes.number
  }
  
  const defaultProps = {
      initialPage: 1
  }
  
  class Pagination extends React.Component {
  constructor(props) {
      super(props);
      this.state = { pager: {} };
  }
  
  componentWillMount() {
      this.setPage(this.props.initialPage);
  }
  
  setPage(page) {
      var items = this.props.items;
      var pager = this.state.pager;
  
      if (page &lt; 1 || page &gt; pager.totalPages) {
          return;
      }
  
      // get new pager object for specified page
      pager = this.getPager(items.length, page);
  
      // get new page of items from items array
      var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1);
  
      // update state
      this.setState({ pager: pager });
  
      // call change page function in parent component
      this.props.onChangePage(pageOfItems);
  }
  
  getPager(totalItems, currentPage, pageSize) {
      // default to first page
      currentPage = currentPage || 1;
  
      // default page size is 10
      pageSize = pageSize || 5;
  
      // calculate total pages
      var totalPages = Math.ceil(totalItems / pageSize);
  
      var startPage, endPage;
      if (totalPages &lt;= 10) {
          // less than 10 total pages so show all
          startPage = 1;
          endPage = totalPages;
      } else {
          // more than 10 total pages so calculate start and end pages
          if (currentPage &lt;= 6) {
              startPage = 1;
              endPage = 10;
          } else if (currentPage + 4 &gt;= totalPages) {
              startPage = totalPages - 9;
              endPage = totalPages;
          } else {
              startPage = currentPage - 5;
              endPage = currentPage + 4;
          }
      }
  
      // calculate start and end item indexes
      var startIndex = (currentPage - 1) * pageSize;
      var endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
  
      // create an array of pages to ng-repeat in the pager control
      var pages = [...Array((endPage + 1) - startPage).keys()].map(i =&gt; startPage + i);
  
      // return object with all pager properties required by the view
      return {
          totalItems: totalItems,
          currentPage: currentPage,
          pageSize: pageSize,
          totalPages: totalPages,
          startPage: startPage,
          endPage: endPage,
          startIndex: startIndex,
          endIndex: endIndex,
          pages: pages
      };
  }
  
  render() {
      var pager = this.state.pager;
  
      return (
          &lt;ul className="pagination"&gt;
              &lt;li className={pager.currentPage === 1 ? 'disabled' : ''}&gt;
                  &lt;a onClick={() =&gt; this.setPage(pager.currentPage - 1)}&gt;&amp;lt; back&lt;/a&gt;
              &lt;/li&gt;
              {pager.pages.map((page, index) =&gt;
                  &lt;li key={index} className={pager.currentPage === page ? 'active' : ''}&gt;
                      &lt;a onClick={() =&gt; this.setPage(page)}&gt;{page}&lt;/a&gt;
                  &lt;/li&gt;
              )}
              &lt;li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}&gt;
                  &lt;a onClick={() =&gt; this.setPage(pager.currentPage + 1)}&gt;next &amp;gt;&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
      );
  }
  }
  
  Pagination.propTypes = propTypes;
  Pagination.defaultProps
  export default Pagination;
  </code></pre>
  
  <p>EDIT: A part of the pagination has been moved to table component and now it works correctly</p>