为什么useFetcher会导致重新渲染无限循环?
我有一个输入。在输入的每一个更改中,我想致电API。
这是代码的简化版本:
// updated by input
const [urlText, setUrlText] = useState("");
const fetcher = useFetcher();
useEffect(() => {
if (urlText === "" || !fetcher) return;
fetcher.load(`/api/preview?url=${urlText}`);
}, [urlText]);
问题是,当我将urlText
放入依赖项数组中时,有一个无限的渲染循环,并且React Soppaim索赔问题是我可能正在更新状态。 使用效果
。但是,据我所知,我没有更新钩子内部的任何状态,因此我不确定为什么会发生无限的重新渲染。
有什么想法吗?
代码的完整版本是:
注意:该错误仍然没有访问或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>
);
}
I have an input. On every change to the input, I want to call an 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
. 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.
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>
);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您遇到的问题是Fetcher在整个获取过程中都进行了更新。这会导致您的效果重新运行,并且由于您正在调用
load
,因此它正在重复周期。您应该检查
fetcher.state
以查看何时提取。https://remix.run/docs.run/docs/en/en/en/v1/api/remix#usefetcher
The problem you're having is that fetcher is updated throughout the fetch process. This is causing your effect to re-run, and since you are calling
load
again, it is repeating the cycle.You should be checking
fetcher.state
to see when to fetch.https://remix.run/docs/en/v1/api/remix#usefetcher
您可以通过在
usefetcher
挂钩中设置状态,请检查load> load
方法的代码 usefetcher 。You might by setting state in
useFetcher
hook, please check code ofload
method fromuseFetcher
.更新:我很傻。
使用的ebouncous
返回一个数组。Update: I'm silly.
useDebounce
returns an array.