Как реализовать разбиение на страницы на стороне сервера с помощью реагирующей таблицы?

Я новичок в реагирующей таблице. Я пытаюсь реализовать разбивку на страницы на стороне сервера, но не понимаю, как обнаружить изменение страницы в новой версии таблицы реагирования. Я использую правильные данные для выборки. Я не могу обнаружить изменение. Каждый раз, когда я нажимаю кнопку «Далее», я должен иметь возможность изменять значение смещения в конечной точке API с шагом 20 для получения новых данных. Я не могу выполнить эту операцию. Пожалуйста, помогите.

import React, { useEffect, useState, useMemo } from 'react'
import { URLs } from "../../../Config/url";
import cookie from 'react-cookies';
import "./OrderManagementScreen.css"
import { useTable, usePagination, useSortBy } from 'react-table';
import styled from 'styled-components';


const Styles = styled.div`
padding: 1rem;

table {
  border-spacing: 0;
  border: 1px solid lightgray;
  width: 100%;
  text-align: "center" !important;

  tr {
    :last-child {
      td {
        border-bottom: 0;
        text-align: "center" !important;
      }
    }
  }
  th {
    padding: 3px;
    box-shadow: 0px 5px 7px 2px lightgrey;
  }
  td {
    padding: 5px;
  }
  th,
  td {
    margin: 0;
    text-align: "center";
    border-bottom: 1px solid #73737361;
    border-right: 1px solid #73737361;

    :last-child {
      border-right: 0;
    }
  }
}
.pagination {
}
`;

const WrapperTable = styled.div`
background: #ffffff;
box-shadow: 3px 3px 2px 0px rgb(162 161 161 / 75%) !important;
border-radius: 5px;
`


const Table = ({ columns, data }) => {
  // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,

    page, // Instead of using 'rows', we'll use page,
    // which has only the rows for the active page

    // The rest of these things are super handy, too ;)
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize, sortBy },
  } = useTable(
    {
      columns,
      data,
      initialState: { pageIndex: 0 },
    },
    useSortBy,
    usePagination
  );
  // const sorted = column.isSorted ? (column.isSortedDesc ? " 🔽" : " 🔼") : "";
  // const sorted = column.isSorted ? (column.isSortedDesc ? {borderTop:"1px solid "} :{borderTop:"1px solid "}) : "";
  // Render the UI for your table
  return (
    <>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                  {column.render("Header")}
                  {/* Add a sort direction indicator */}
                  <span>
                    {column.isSorted
                      ? column.isSortedDesc
                        ? " 🔽"
                        : " 🔼"
                      : ""}
                  </span>
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row, i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
      {/* 
      Pagination can be built however you'd like. 
      This is just a very basic UI implementation:
      */}
      <div className = "pagination">
        {/* <button
          className = "pagination-btn"
          onClick = {() => gotoPage(0)}
          disabled = {!canPreviousPage}
        >
          First
        </button> */}
        <button
          className = "pagination-btn"
          onClick = {() => previousPage()}
          disabled = {!canPreviousPage}
        >
          Previous
        </button>
        <span className = "pagination-btn text-center">
          Page{" "}
          <strong>
            {pageIndex + 1} of {pageOptions.length}
          </strong>{" "}
        </span>
        <button
          className = "pagination-btn"
          onClick = {() => nextPage()}
          disabled = {!canNextPage}
        >
          Next
        </button>
        {/* <button
        className = "pagination-btn"
          onClick = {() => gotoPage(pageCount - 1)}
          disabled = {!canNextPage}
        >
          Last
        </button> */}

        {/* <span>
          | Go to page:{' '}
          <input
            type = "number"
            defaultValue = {pageIndex + 1}
            onChange = {e => {
              const page = e.target.value ? Number(e.target.value) - 1 : 0
              gotoPage(page)
            }}
            style = {{ width: '100px' }}
          />
        </span> */}
        {/* <select
          value = {pageSize}
          onChange = {e => {
            setPageSize(Number(e.target.value))
          }}
        >
          {[10, 20, 30, 40, 50].map(pageSize => (
            <option key = {pageSize} value = {pageSize}>
              Show {pageSize}
            </option>
          ))}
        </select> */}
      </div>
    </>
  );
};

const OrderManagementScreen = () => {
  const token = cookie.load("userObj").data.token;
  //orderid, outletname, area, distributor, ordervalue, outlet type, discount group, salesofficer,order
  const [tableData, SetData] = useState([]);
  const [loading, setLoading] = React.useState(false);
  const fetchIdRef = React.useRef(0);
  const sortIdRef = React.useRef(0);

  const columns = React.useMemo(
    () => [
      {
        Header: "Order Id",
        accessor: "id",
      },
      {
        Header: "Outlet Name",
        id: "outlet_detail",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.name);
          });
          return output.join(', ');
        }
      },
      {
        Header: "Area",
        id: "area",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.area__name);
          });
          return output.join(', ');
        }
      },
      {
        Header: "Distributor",
        id: "distributor",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.distributor_name);
          });
          return output.join(', ');
        }
      },
      {
        Header: "Order Value",
        accessor: "total_price",
      },
      {
        Header: "Outlet Type",
        id: "outlet_type__name",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.final_value);
          });
          return output.join(', ');
        }
      },
      {
        Header: "Discount Group",
        id: "discount__name",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.discount__name);
          });
          return output.join(', ');
        }
      },
      {
        Header: "Sales Officer",
        id: "sales_officer",
        accessor: data => {
          let output = [];
          data.outlet_detail.map(item => {
            return output.push(item.by_user__username);
          });
          return output.join(', ');
        }
      }
    ],
    []
  );
  const listdata = async () => {
    const response = await fetch(`${URLs.orderUrl}?limit=20&offset=0`, {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Token ${token}`
      }
    })

    const data = await response.json();
    SetData(data);
  }


  const fetchData = React.useCallback(({ pageSize, pageIndex, sortBy }) => {
    // 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
  console.info(pageIndex);
    console.info(pageSize);
    const fetchId = ++fetchIdRef.current;

    // Set the loading state
    setLoading(true);

    // We'll even set a delay to simulate a server here
    setTimeout(() => {
      // Only update the data if this is the latest fetch
      if (fetchId === fetchIdRef.current) {
        const startRow = pageSize * pageIndex;
        
        const endRow = startRow + pageSize;
        if (sortBy.length === 0) {
          SetData(tableData.sort().slice(startRow, endRow));
        } else {
          SetData(
            tableData
              .sort((a, b) => {
                const field = sortBy[0].id;
                const desc = sortBy[0].desc;
                if (a[field] < b[field]) {
                  return desc ? -1 : 1;
                }
                if (a[field] > b[field]) {
                  return desc ? 1 : -1;
                }
                return 0;
              })
              .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);
  }, []);

  useEffect(() => {
    listdata();
  }, [])
  return (
    <div className = "p-3 text-center">
      <h4>Order Management</h4>
      <WrapperTable>
        <Styles>
          <Table columns = {columns} fetchData = {fetchData} data = {tableData} />
        </Styles>
      </WrapperTable>
    </div>
  )
}

export default OrderManagementScreen;
<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>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
12
0
8 367
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вам нужно понять основную разницу между нумерацией страниц на стороне клиента и на стороне сервера.

В пагинации на стороне клиента у нас уже есть все данные для всех страниц, которые нам нужно отобразить в таблице, а это значит, что мы также знаем общее количество (totalcount=pagesize*number of pages).
Теперь сравните это с разбиением на страницы на стороне сервера. Мы получим фрагмент данных, который мы запрашиваем, что означает, что мы сохраняем размер страницы равным 10 и у нас есть 100 данных на нашем сервере, но поскольку мы запросили 10, мы получим только 10 элементов. Тогда как компонент пагинации узнает, какое общее количество страниц ему нужно отобразить?
Вот почему нам также нужен общий счет с сервера, когда мы извлекаем данные. Но подождите, нам это нужно каждый раз? Ну, это зависит от вашего варианта использования. В общем, нам нужно общее количество либо в первый раз, либо в случае, если мы делаем какой-либо поиск или фильтрацию.

Теперь перейдем к вашему решению-
В таблице реагирования, если мы явно не установили флаг manualPagination как true, тогда он будет обрабатывать количество страниц на основе предоставленных вами данных и размера страницы, поэтому он автоматически обработает разбиение на страницы. Итак, нам нужно сделать это manualPagination, поскольку true в options мы передали useTable, а также нам нужно указать общее количество страниц, которое равно pageCount. Так что это будет что-то вроде

useTable(
    {
      columns,
      data,
      initialState: { pageIndex: 0 },
    },
    useSortBy,
    usePagination,
    manualPagination: true,
    pageCount: (totalcount/pagesize),//you can handle this calculation in your fetchdata method
  );

а затем добавьте вызов выборки данных внутри нового useEffect с вашим индексом страницы и размер страницы как зависимости

React.useEffect(() => {
    fetchData({ pageIndex, pageSize })
  }, [fetchData, pageIndex, pageSize])

Я надеюсь, что это решит вашу проблему. Это также хорошо объяснено в документации реагирующей таблицы с ​​подходящим кодшеринговым примером. Загляните сюда

Другие вопросы по теме