When I click on a button inside a component I send back to the Page an id
via function const readUrl
. Now I'm trying to send client-side that id
to an /api/dat/[id].js
route where inside it basically searches for that id within mongodb and res.send
back to the Page the JSON result.
So via SWR, I'm dealing with the API route client-side and I use two useState
to deal with id from a button click and result from API to pass it to the react DOM.
The issue is I get:
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
This is my api/dat/[id].js
:
import { connectToDatabase } from "../../utils/mongodb"
export default async function ({ query: { id } }, res) {
const { db } = await connectToDatabase();
const dataID = id
const foundData = /* query to mongodb.toArray() */
if (foundData.length) {
res.status(200).send({ data: foundData[0] })
} else {
res.status(404).json({ message: `Data ${id} not found.` })
}
res.end()
}
This is the code in my page:
const [urlNow, setUrlNow] = useState(null);
const [urlData, setUrlData] = useState(null);
const readUrl = (url) => {
setUrlNow(url)
return true
}
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data, error } = useSWR(readUrl ? `/api/dat/${urlNow}` : null, fetcher)
// if (error) return <div>{error.message}</div>
// if (!data) return <div>Loading...</div>
if (data) setUrlData(data.data)
return (
...
{urlData
? <Component data={urlData} />
: <ComponentWithButton readUrl={readUrl} />
}
useSWR
as it is set above fires up only if function readUrl
returns true
, as SWR docs say, so I think it should fetch the API route only if the button gets clicked, at least that was the idea.
You should replace the condition in useSWR()
to use urlNow
rather than the readUrl
function.
Some states/variables can also be cleaned up to make the code simpler, and avoid the infinite rerender caused by setUrlData(data.data)
.
const [urlNow, setUrlNow] = useState(null);
const readUrl = (url) => {
setUrlNow(url)
}
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data, error } = useSWR(urlNow ? `/api/dat/${urlNow}` : null, fetcher)
// if (error) return <div>{error.message}</div>
// if (!data) return <div>Loading...</div>
return (
{data
? <Component data={data} />
: <ComponentWithButton readUrl={readUrl} />
}
//...
)