[英]Why is useFetcher causing an re-render infinite loop?
I have an input.我有一个输入。 On every change to the input, I want to call an API.在每次更改输入时,我都想调用一个 API。
Here's a simplified version of the code:这是代码的简化版本:
// updated by input
const [urlText, setUrlText] = useState("");
const fetcher = useFetcher();
useEffect(() => {
if (urlText === "" || !fetcher) return;
fetcher.load(`/api/preview?url=${urlText}`);
}, [urlText]);
The issue is, when I put urlText
inside of the dependencies array, there is an infinite rendering loop, and React claims the issue is I might be updating state inside of the useEffect
.问题是,当我将urlText
放在依赖项数组中时,会出现无限渲染循环,而 React 声称问题是我可能正在更新useEffect
内部的状态。 However, as far as I can tell, I'm not updating any state inside of the hook, so I'm not sure why an infinite re-render is happening.但是,据我所知,我没有更新钩子内的任何状态,所以我不确定为什么会发生无限重新渲染。
Any thoughts?有什么想法吗?
The fuller version of the code is:代码的完整版本是:
Note: The bug still happens without the debounce, or the useMemo
, all of that stuff is roughly irrelevant.注意:在没有去抖动或useMemo
的情况下,该错误仍然会发生,所有这些内容大致无关紧要。
export default function () {
const { code, higlightedCode } = useLoaderData<API>();
const [urlText, setUrlText] = useState("");
const url = useMemo(() => getURL(prefixWithHttps(urlText)), [urlText]);
const debouncedUrl = useDebounce(url, 250);
const fetcher = useFetcher();
useEffect(() => {
if (url === null || !fetcher) return;
fetcher.load(`/api/preview?url=${encodeURIComponent(url.toString())}`);
}, [debouncedUrl]);
return (
<input
type="text"
placeholder="Paste URL"
className={clsx(
"w-full rounded-sm bg-gray-800 text-white text-center placeholder:text-white"
//"placeholder:text-left text-left"
)}
value={urlText}
onChange={(e) => setUrlText(e.target.value)}
></input>
);
}
您可以通过在useFetcher
钩子中设置状态,请从useFetcher
检查load
方法的代码。
The problem you're having is that fetcher is updated throughout the fetch process.您遇到的问题是 fetcher 在整个提取过程中都会更新。 This is causing your effect to re-run, and since you are calling load
again, it is repeating the cycle.这导致您的效果重新运行,并且由于您再次调用load
,它正在重复循环。
You should be checking fetcher.state
to see when to fetch.您应该检查fetcher.state
以查看何时获取。
useEffect(() => {
// check to see if you haven't fetched yet
// and we haven't received the data
if (fetcher.state === 'idle' && !fetcher.data) {
fetcher.load(url)
}
}, [url, fetcher.state, fetcher.data])
https://remix.run/docs/en/v1/api/remix#usefetcher https://remix.run/docs/en/v1/api/remix#usefetcher
Update: I'm silly.更新:我很傻。 useDebounce
returns an array. useDebounce
返回一个数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.