When using fetcher like
const fetcher = (url, data) => axios.post(url, data).then(res=>res.data)
const {data, error} = useSWR(['/api/v1/reports/statistics', data], fetcher)
Endless API calls. Infinite calling
But this happens only in SSR. And works fine with client Side rending.
Make only one API call during the server side rendering
const fetcher = (url, data) => axios.post(url, data).then(res=>res.data)
const StatisticsTable = ({criteria={}}) => {
const {data, error} = useSWR(['/api/v1/reports/statistics', criteria], fetcher)
return <div>{data}</div>
}
SWR version - _0.3.3 to 0.3.5_
const StatisticsTable = ({ criteria={} /** this will create a new object everytime **/}) => {
const {data, error} = useSWR(['/api/v1/reports/statistics', criteria], fetcher)
return <div>{data}</div>
}
Could you try this ?
const default = {}
const StatisticsTable = ({ criteria= default}) => {
const {data, error} = useSWR(['/api/v1/reports/statistics', criteria], fetcher)
return <div>{data}</div>
}
It would be great if you can provide codesandbox example
Tried changing that.
Anyways, that doesn't seem to be a problem. because it worked fine with client side rendering.
However have reproduced the same in your sandbox.
You can see multiple calls going to endpoint /day
Here is the link. I have shared to your Id as well.
https://codesandbox.io/s/nice-wave-wy3ib?file=/pages/index.js
I have tested with axios and it works fine without SWR.
@vishnuvchandar I tried on your codesanbod example, the issue is when you pass an object to useSWR as first argument within next.js, each time the hashed key will be different

the weakmap in hash lib looks like following

the solution to this could be
+const payload = { test: "message" }
export default function DayPage() {
- const { data, error } = useSWR(["/api/v1/day", { test: "message" }], fetcher);
+ const { data, error } = useSWR(["/api/v1/day", payload], fetcher);
return <div>Hello Day {data}</div>;
}
// Don’t do this! Deps will be changed on every render.
useSWR(['/api/user', { id }], query)
// Instead, you should only pass “stable” values.
useSWR(['/api/user', id], (url, id) => query(url, { id }))
https://swr.vercel.app/docs/arguments#passing-objects
Hope this will help
This doesnt solve my purpose. The criteria cannot be a default value. Its susceptible to change.
I want that to be a dynamically changing object based on the action i perform on the parent component.
Say i need to change a date range or something. On every state change of Criteria object, it has to make a call to my API with the updated values.
How should i do that with this apporoach??
How am i supposed to handle below scenario.
const StatisticsTable = ({ criteria }) => {
const {data, error} = useSWR(criteria && ['/api/v1/reports/statistics', criteria], fetcher)
return <div>{data}</div>
}
is it possible to pick out some primitive values (string, numbers or references of same object) from criteria and pass them as key of useSWR hook?
like
const {date} = criteria
useSWR(['/api/v1/reports/statistics', date.month, date.day], (url, month, day) => ...)
then it's easier for swr to convert the complex key as a consistent id to memorize. otherwise if the key is a different object each render, like a changing react prop, would be difficult to have an algorithm to mark it as consistent key during the entire runtime.
You can create a custom hook like this. But you should know deepcompare might cause some performance issues.
import { dequal } from "dequal/lite"
function useObjectSWR(key, fn, option) {
const stableKey = React.useRef(key);
React.useEffect(() => {
// This could be slow
if (!dequal(stableKey.current, key)) stableKey.current = key;
});
return useSWR(stableKey.current, fn, option);
}
export default function DayPage({ message }) {
const { data, error } = useObjectSWR(["/api/v1/day", message], fetcher);
return <div>{data}</div>;
}
is it possible to pick out some primitive values (string, numbers or references of same object) from
criteriaand pass them as key of useSWR hook?like
const {date} = criteria useSWR(['/api/v1/reports/statistics', date.month, date.day], (url, month, day) => ...)then it's easier for swr to convert the complex key as a consistent id to memorize. otherwise if the key is a different object each render, like a changing react prop, would be difficult to have an algorithm to mark it as consistent key during the entire runtime.
This shud work. But the only problem is not all the time all objects will be sent! Since its a filter criteria, it keeps building. However, i thought of Stringifying and Parsing it on the api side, which i believe shud work. Lemme know if its a right approach!.....
You can create a custom hook like this. But you should know deepcompare might cause some _performance issues_.
import { dequal } from "dequal/lite" function useObjectSWR(key, fn, option) { const stableKey = React.useRef(key); React.useEffect(() => { // This could be slow if (!dequal(stableKey.current, key)) stableKey.current = key; }); return useSWR(stableKey.current, fn, option); } export default function DayPage({ message }) { const { data, error } = useObjectSWR(["/api/v1/day", message], fetcher); return <div>{data}</div>; }
Wo wo wo! This is way more complicated for what i need. As i mentioned in previous comment lemme know if Stringify Parse is a better way to handle this..
Stringifying surly can work! another way is to call useMemo to memorize criteria only when some props of it changed.
for swr side it just wants to have a consistent reference for different key argument when the value of key arg is really different.
close this issue since it's as designed, conversation can still be carried on here.