Reputation: 63
i am trying to fetch data from next api route but the useEffect method is not firing up on page reload. also i can't make this component async as nextJS does'nt allow async functions on client components(use client)
page.tsx:
"use client";
import { useEffect, useState } from "react";
import DataTable from "./components/table";
import { Resizable } from "re-resizable";
const SamplePage: React.FC = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch("/api/data")
.then((res) => res.json())
.then((data) => {
setData(data);
console.log("data");
});
}, []);
console.log(data, "dataaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
const headers = [
"Timestamp",
"Purchase Id",
"Mail",
"Name",
"Source",
"Status",
"Select",
];
const rows = [
{
Timestamp: "2023-07-15",
"Purchase Id": "P001",
Mail: "[email protected]",
Name: "John Doe",
Source: "Web",
Status: "Completed",
Select: "Select",
},
{
Timestamp: "2023-07-16",
"Purchase Id": "P002",
Mail: "[email protected]",
Name: "Jane Smith",
Source: "Mobile",
Status: "Waiting",
Select: "Select",
},
{
Timestamp: "2023-07-17",
"Purchase Id": "P003",
Mail: "[email protected]",
Name: "Mike Johnson",
Source: "Web",
Status: "Failed",
Select: "Select",
},
{
Timestamp: "2023-07-18",
"Purchase Id": "P004",
Mail: "[email protected]",
Name: "Emily Brown",
Source: "Web",
Status: "Completed",
Select: "Select",
},
{
Timestamp: "2023-07-19",
"Purchase Id": "P005",
Mail: "[email protected]",
Name: "David Wilson",
Source: "Mobile",
Status: "Waiting",
Select: "Select",
},
{
Timestamp: "2023-07-20",
"Purchase Id": "P006",
Mail: "[email protected]",
Name: "Sarah Davis",
Source: "Web",
Status: "Failed",
Select: "Select",
},
{
Timestamp: "2023-07-21",
"Purchase Id": "P007",
Mail: "[email protected]",
Name: "Alex Johnson",
Source: "Mobile",
Status: "Completed",
Select: "Select",
},
{
Timestamp: "2023-07-22",
"Purchase Id": "P008",
Mail: "[email protected]",
Name: "Emma Smith",
Source: "Web",
Status: "Waiting",
Select: "Select",
},
{
Timestamp: "2023-07-23",
"Purchase Id": "P009",
Mail: "[email protected]",
Name: "James Wilson",
Source: "Web",
Status: "Failed",
Select: "Select",
},
{
Timestamp: "2023-07-24",
"Purchase Id": "P010",
Mail: "[email protected]",
Name: "Olivia Brown",
Source: "Mobile",
Status: "Completed",
Select: "Select",
},
];
const [state, setState] = useState({ width: "95%", height: "80%" });
return (
<>
<Resizable
style={{ border: "1px solid black" }}
size={{ width: state.width, height: state.height }}
onResizeStop={(e, direction, ref, d) => {
setState({
width: state.width + d.width,
height: state.height + d.height,
});
}}
>
<DataTable
headers={headers}
rows={rows}
caption="Bookings Details (pagination,sorting added)"
sortable
pagination
colorScheme="teal"
/>
</Resizable>
</>
);
};
export default SamplePage;
DataTable.tsx
"use client"
import {
Table,
Thead,
Tbody,
Tr,
Th,
Td,
Box,
Input,
Flex,
} from "@chakra-ui/react";
import { useState } from "react";
import styles from "./table.module.css";
import { Button, ButtonGroup } from "@chakra-ui/react";
import {
ChevronRightIcon,
ChevronLeftIcon,
SearchIcon,
ChevronDownIcon,
ChevronUpIcon,
} from "@chakra-ui/icons";
import dynamic from "next/dynamic";
interface DataTableProps {
headers: string[];
rows: Record<string, string | number>[];
caption?: string;
sortable?: boolean;
pagination?: boolean;
itemsPerPage?: number;
tableStyling?: string;
colorScheme?: string;
}
const DataTable: React.FC<DataTableProps> = ({
headers,
rows,
caption,
sortable,
pagination,
itemsPerPage,
tableStyling,
colorScheme,
}) => {
const [sortConfig, setSortConfig] = useState<{
column: string;
ascending: boolean;
}>({
column: "",
ascending: true,
});
const [currentPage, setCurrentPage] = useState(1);
const [perPage, setPerPage] = useState(itemsPerPage || 5);
const [searchTerms, setSearchTerms] = useState<{ [column: string]: string }>(
{}
);
const [resizableColumns, setResizableColumns] = useState<string[]>([]);
const handleHeaderClick = (column: string) => {
if (!sortable) return;
if (sortConfig.column === column) {
setSortConfig({ ...sortConfig, ascending: !sortConfig.ascending });
} else {
setSortConfig({ column, ascending: true });
}
};
const sortRows = () => {
if (!sortConfig.column) return rows;
const sortedRows = [...rows];
sortedRows.sort((a, b) => {
const valueA = a[sortConfig.column];
const valueB = b[sortConfig.column];
if (typeof valueA === "string" && typeof valueB === "string") {
return sortConfig.ascending
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
} else {
return sortConfig.ascending
? (valueA as number) - (valueB as number)
: (valueB as number) - (valueA as number);
}
});
return sortedRows;
};
const filterRows = () => {
return rows.filter((row) => {
return Object.entries(searchTerms).every(([column, searchTerm]) => {
const value = row[column]?.toString().toLowerCase();
return value?.includes(searchTerm.toLowerCase());
});
});
};
const getFilteredAndSortedRows = () => {
const filteredRows = filterRows();
const sortedRows = sortRows();
return sortedRows.filter((row) => filteredRows.includes(row));
};
const renderRows = () => {
const sortedAndFilteredRows = getFilteredAndSortedRows();
const startIndex = (currentPage - 1) * perPage;
const endIndex = startIndex + perPage;
return sortedAndFilteredRows
.slice(startIndex, endIndex)
.map((row, index) => (
<Tr key={index}>
{headers.map((header, index) => {
return (
<Td key={index}>
<Box
className={
row[header] === "Completed"
? `${styles.completed} ${styles.status}`
: row[header] === "Waiting"
? `${styles.waiting} ${styles.status}`
: row[header] === "Failed"
? `${styles.failed} ${styles.status}`
: row[header] === "Select"
? `${styles.yes} ${styles.status}`
: ""
}
>
{row[header]}
</Box>
</Td>
);
})}
</Tr>
));
};
const renderPagination = () => {
const totalPages = Math.ceil(filterRows().length / perPage);
const previousDisabled = currentPage === 1;
const nextDisabled = currentPage === totalPages;
return (
<div className={styles.pagination}>
<ButtonGroup>
<Button
className={styles.paginationBtn}
onClick={() =>
setCurrentPage(currentPage === 1 ? currentPage : currentPage - 1)
}
disabled={previousDisabled}
leftIcon={<ChevronLeftIcon fontSize={"2rem"} color={"white"} />}
></Button>
<Button
className={styles.paginationBtn}
onClick={() =>
setCurrentPage(
currentPage === totalPages ? currentPage : currentPage + 1
)
}
disabled={nextDisabled}
rightIcon={<ChevronRightIcon fontSize={"2rem"} color={"white"} />}
></Button>
</ButtonGroup>
<span className={styles.currentPage}>
Page {currentPage} of {totalPages}
</span>
<span className={styles.itemsPerPage}>
Items per page:
<select
value={perPage}
onChange={(e) => {
setCurrentPage(1);
setPerPage(parseInt(e.target.value));
}}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={15}>15</option>
</select>
</span>
</div>
);
};
return (
<Table
className={styles.tableStyle}
size={"sm"}
variant={tableStyling}
colorScheme={colorScheme}
>
{caption && (
<caption>
<div
style={{ marginBottom: "2rem", fontWeight: "bold" }}
className="captionStyle"
>
{caption}
</div>
</caption>
)}
<Thead>
<Tr>
{headers.map((header, index) => (
<Th
key={index}
onClick={() => handleHeaderClick(header)}
cursor={sortable ? "pointer" : "default"}
>
{header}
</Th>
))}
</Tr>
<Tr>
{headers.map((header, index) => (
<Td key={index}>
<Flex align="center">
<Input
size="sm"
variant="outline"
placeholder={`Search ${header}`}
value={searchTerms[header] || ""}
onChange={(e) =>
setSearchTerms((prevSearchTerms) => ({
...prevSearchTerms,
[header]: e.target.value,
}))
}
pr="2.5rem"
/>
{/* <SearchIcon
boxSize={4}
color="gray.400"
position="absolute"
right="0.75rem"
/> */}
</Flex>
</Td>
))}
</Tr>
</Thead>
<Tbody>{renderRows()}</Tbody>
{pagination && renderPagination()}
</Table>
);
};
export default DataTable;
tried creating different utils.ts file for fetching data but that does'nt work either
Upvotes: 3
Views: 1607
Reputation: 41
Possibly the cache is turned on and preventing a new request from being made.
Try to change your fetch
function in your correspondent /api
file, to use no-store (no cache) as recommended in next.js
documentation option, to fetches the resource from the remote server on every request without looking in the cache.
fetch(`https://...`, { cache: 'no-store' })
Hope this helps!
Upvotes: 0