Hi i'm trying to use SWR in my React app, but this generate an error because the data its ever undefined and when i check the network, i can se three calls to the api:
Table component:
import React, { , useEffect } from "react";
import {ProductService} from "../Services/product-service";
import { useDispatch, useSelector } from "react-redux";
import LinearProgress from "@mui/material/LinearProgress";
import useSWR from "swr";
function TableTransactions({ clientUserName, productNumber }) {
const dispatch = useDispatch();
const {data, isLoading, error} = useSWR(["transactions",clientUserName, productNumber,10],
ProductService.GetListTransactionsByParams(clientUserName, productNumber, 10));
useEffect(()=>{
(async()=>{
//...;
})();
},[clientUserName, productNumber]);
if(error) return <div>failed to load</div>
if(isLoading) return <LinearProgress/>
return (
<>
<Box>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>
<b>Tipo transacción</b>
</TableCell>
<TableCell >
<b>Fecha</b>
</TableCell>
<TableCell >
<b>Valor</b>
</TableCell>
<TableCell >
<b>Producto origen</b>
</TableCell>
<TableCell >
<b>Producto destino</b>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row) => (
<TableRow
key={uuidv4()}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{row.typeTransaction.name}
</TableCell>
<TableCell >{row.creationDate}</TableCell>
<TableCell >{row.explicitValue}</TableCell>
<TableCell >{row.originProductNumber}</TableCell>
<TableCell >{row.destinyProductNumber}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
</>
);
}
export default TableTransactions;
My function caller fetcher:
async function GetListTransactionsByParams(userName, productNumber, maxCount=10){
try{
var objSearch = {clientUserName: userName, productNumber: productNumber, maxCount:maxCount};
let route = ClientSettings.UrlBaseInfoBankApi+"ProductInfo/ListTransactionsClient";
let bearer = null;
var response = await fetch(route,{
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer,
},
//credentials: "include",
body: JSON.stringify(objSearch)
});
await HandleResponseService(response);
let json = await response.clone().json();
if (response.status == 200 && json.response === true && json.error === "") {
return json.data;
}
return null;
}catch(err){
throw new Error("Error connecting or timeout service: "+err);
return null;
}
}
I try to check {data ? && data.mapa(...)} but this only fix the console error, and data continues ever being undefined.
I had to change the way to return data from my fetcher function:
const GetListTransactionsByParams= async(userName, productNumber, maxCount=10, fromDate, untilDate)=>{
try{
//...
let route = ClientSettings.UrlBaseInfoBankApi+"ProductInfo/ListTransactionsClient";
let bearer = null;
var response = await fetch(route,{
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer,
},
//credentials: "include",
body: JSON.stringify(objSearch)
});
await HandleResponseServiceFetch(response);
const data = await response.clone().json();
return data.data;
}catch(err){
throw new Error("An error occurred while fetching the data: "+err);
}
}
And i had to change the way to generate a key for swr, apply adittional configuration for avoid automatic re-fetch and use ()=> for apply direct cll to fetcher:
function generateKey(clientUserName, productNumber, maxCount) {
return `${clientUserName}-${productNumber}-${maxCount}`;
}
const key = generateKey(clientUserName, productNumber, maxCount);
const {
data = [],
isLoading,
isValidating,
error,
mutate} = useSWR([key],() => ProductService.GetListTransactionsByParams(
clientUserName,
productNumber,
maxCount,
dateFrom,
dateUntil
),
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
});