使用 SWR 请求 API 路由时出现太多重新呈现错误

Too many re-renders error when making request to API route on click with SWR

当我单击组件内的按钮时,我通过函数 const readUrlid 发送回页面。现在我正在尝试将 id 的客户端发送到 /api/dat/[id].js 路由,其中​​基本上在 mongodb 和 res.send 内搜索该 id 返回页面 JSON结果。

所以通过 SWR,我正在处理客户端的 API 路由,我使用两个 useState 来处理来自按钮点击的 id 和来自 API 的结果将其传递给反应 DOM.

问题是我得到:

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

这是我的 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()
}

这是我页面中的代码:

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 正如 SWR 文档所说,只有当函数 readUrl returns true 才会触发,所以我认为它应该获取 API 仅当按钮被点击时路由,至少那是想法。

您应该替换 useSWR() 中的条件以使用 urlNow 而不是 readUrl 函数。

也可以清理一些states/variables,让代码更简单,避免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} />
    }
    //...
)