title: React-Table Sort with Pagination Unexpected Results
body: <p>Getting some unexpected results while using react-table. I've combined examples for pagination-controlled and sorting from <a href="https://github.com/tannerlinsley/react-table/tree/master/examples" rel="nofollow noreferrer">react-table examples</a>. The issue i'm experiencing is the table hooks seem to be resetting the page index back to default on a second re-render. This is resulting in fetchData being called twice when paging back and forth. Below is a reproduction of the problem i'm facing:</p>
  
  <pre><code>import React from "react";
  import styled from "styled-components";
  import { useTable, usePagination, useSortBy } from "react-table";
  
  import makeData from "./makeData";
  
  const Styles = styled.div`
    `
  
  // Let's add a fetchData method to our Table component that will be used to fetch
  // new data when pagination state changes
  // We can also add a loading state to let our table know it's loading new data
  function Table({
    columns,
    data,
    fetchData,
    loading,
    pageCount: controlledPageCount
  }) {
    const {
      getTableProps,
      getTableBodyProps,
      headerGroups,
      prepareRow,
      page,
      canPreviousPage,
      canNextPage,
      pageOptions,
      pageCount,
      gotoPage,
      nextPage,
      previousPage,
      setPageSize,
      // Get the state from the instance
      state: { pageIndex, pageSize }
    } = useTable(
      {
        columns,
        data,
        initialState: { pageIndex: 0 }, // Pass our hoisted table state
        manualPagination: true, // Tell the usePagination
        // hook that we'll handle our own data fetching
        // This means we'll also have to provide our own
        // pageCount.
        pageCount: controlledPageCount
      },
      useSortBy,
      usePagination
    );
  
    // Listen for changes in pagination and use the state to fetch our new data
    React.useEffect(() =&gt; {
      fetchData({ pageIndex, pageSize });
    }, [fetchData, pageIndex, pageSize]);
  
    // Render the UI for your table
    return (
      &lt;&gt;
        &lt;pre&gt;
          &lt;code&gt;
            {JSON.stringify(
              {
                pageIndex,
                pageSize,
                pageCount,
                canNextPage,
                canPreviousPage
              },
              null,
              2
            )}
          &lt;/code&gt;
        &lt;/pre&gt;
        &lt;table {...getTableProps()}&gt;
          &lt;thead&gt;
            {headerGroups.map(headerGroup =&gt; (
              &lt;tr {...headerGroup.getHeaderGroupProps()}&gt;
                {headerGroup.headers.map(column =&gt; (
                  &lt;th {...column.getHeaderProps(column.getSortByToggleProps())}&gt;
                    {column.render("Header")}
                    &lt;span&gt;
                      {column.isSorted
                        ? column.isSortedDesc
                          ? " "
                          : " "
                        : ""}
                    &lt;/span&gt;
                  &lt;/th&gt;
                ))}
              &lt;/tr&gt;
            ))}
          &lt;/thead&gt;
          &lt;tbody {...getTableBodyProps()}&gt;
            {page.map((row, i) =&gt; {
              prepareRow(row);
              return (
                &lt;tr {...row.getRowProps()}&gt;
                  {row.cells.map(cell =&gt; {
                    return (
                      &lt;td {...cell.getCellProps()}&gt;{cell.render("Cell")}&lt;/td&gt;
                    );
                  })}
                &lt;/tr&gt;
              );
            })}
            &lt;tr&gt;
              {loading ? (
                // Use our custom loading state to show a loading indicator
                &lt;td colSpan="10000"&gt;Loading...&lt;/td&gt;
              ) : (
                &lt;td colSpan="10000"&gt;
                  Showing {page.length} of ~{controlledPageCount * pageSize}{" "}
                  results
                &lt;/td&gt;
              )}
            &lt;/tr&gt;
          &lt;/tbody&gt;
        &lt;/table&gt;
        {/* 
          Pagination can be built however you'd like. 
          This is just a very basic UI implementation:
        */}
        &lt;div className="pagination"&gt;
          &lt;button onClick={() =&gt; gotoPage(0)} disabled={!canPreviousPage}&gt;
            {"&lt;&lt;"}
          &lt;/button&gt;{" "}
          &lt;button onClick={() =&gt; previousPage()} disabled={!canPreviousPage}&gt;
            {"&lt;"}
          &lt;/button&gt;{" "}
          &lt;button onClick={() =&gt; nextPage()} disabled={!canNextPage}&gt;
            {"&gt;"}
          &lt;/button&gt;{" "}
          &lt;button onClick={() =&gt; gotoPage(pageCount - 1)} disabled={!canNextPage}&gt;
            {"&gt;&gt;"}
          &lt;/button&gt;{" "}
          &lt;span&gt;
            Page{" "}
            &lt;strong&gt;
              {pageIndex + 1} of {pageOptions.length}
            &lt;/strong&gt;{" "}
          &lt;/span&gt;
          &lt;span&gt;
            | Go to page:{" "}
            &lt;input
              type="number"
              defaultValue={pageIndex + 1}
              onChange={e =&gt; {
                const page = e.target.value ? Number(e.target.value) - 1 : 0;
                gotoPage(page);
              }}
              style={{ width: "100px" }}
            /&gt;
          &lt;/span&gt;{" "}
          &lt;select
            value={pageSize}
            onChange={e =&gt; {
              setPageSize(Number(e.target.value));
            }}
          &gt;
            {[10, 20, 30, 40, 50].map(pageSize =&gt; (
              &lt;option key={pageSize} value={pageSize}&gt;
                Show {pageSize}
              &lt;/option&gt;
            ))}
          &lt;/select&gt;
        &lt;/div&gt;
      &lt;/&gt;
    );
  }
  
  // Let's simulate a large dataset on the server (outside of our component)
  const serverData = makeData(10000);
  
  function App() {
    const columns = React.useMemo(
      () =&gt; [
        {
          Header: "Name",
          columns: [
            {
              Header: "First Name",
              accessor: "firstName"
            },
            {
              Header: "Last Name",
              accessor: "lastName"
            }
          ]
        },
        {
          Header: "Info",
          columns: [
            {
              Header: "Age",
              accessor: "age"
            },
            {
              Header: "Visits",
              accessor: "visits"
            },
            {
              Header: "Status",
              accessor: "status"
            },
            {
              Header: "Profile Progress",
              accessor: "progress"
            }
          ]
        }
      ],
      []
    );
  
    // We'll start our table without any data
    const [data, setData] = React.useState([]);
    const [loading, setLoading] = React.useState(false);
    const [pageCount, setPageCount] = React.useState(0);
    const fetchIdRef = React.useRef(0);
  
    const fetchData = React.useCallback(({ pageSize, pageIndex }) =&gt; {
      // This will get called when the table needs new data
      // You could fetch your data from literally anywhere,
      // even a server. But for this example, we'll just fake it.
  
      // Give this fetch an ID
      const fetchId = ++fetchIdRef.current;
  
      // Set the loading state
      setLoading(true);
  
      // We'll even set a delay to simulate a server here
      setTimeout(() =&gt; {
        // Only update the data if this is the latest fetch
        if (fetchId === fetchIdRef.current) {
          const startRow = pageSize * pageIndex;
          const endRow = startRow + pageSize;
          setData(serverData.slice(startRow, endRow));
  
          // Your server could send back total page count.
          // For now we'll just fake it, too
          setPageCount(Math.ceil(serverData.length / pageSize));
  
          setLoading(false);
        }
      }, 1000);
    }, []);
  
    return (
      &lt;Styles&gt;
        &lt;Table
          columns={columns}
          data={data}
          fetchData={fetchData}
          loading={loading}
          pageCount={pageCount}
        /&gt;
      &lt;/Styles&gt;
    );
  }
  
  export default App;
  </code></pre>
  
  <p>Here is a codesandbox to observe the behaivor: <a href="https://codesandbox.io/s/lively-paper-1nc6p?file=/src/App.js:0-6884" rel="nofollow noreferrer">codesandbox</a></p>
  
  <p>Also worth noting that the issue does not occur after removing the useSort hook along with call to column.getSortByToggleProps(). </p>