为什么 useFetcher 会导致重新渲染无限循环?

Roy*_*son 1 javascript reactjs remix.run

我有一个输入。每次更改输入时,我都想调用 API。

这是代码的简化版本:

  // updated by input
  const [urlText, setUrlText] = useState("");

  const fetcher = useFetcher();

  useEffect(() => {
    if (urlText === "" || !fetcher) return;
    fetcher.load(`/api/preview?url=${urlText}`);
  }, [urlText]);
Run Code Online (Sandbox Code Playgroud)

问题是,当我放入urlText依赖项数组内部时,存在无限渲染循环,并且 React 声称问题是我可能正在更新useEffect. 然而,据我所知,我没有更新钩子内的任何状态,所以我不确定为什么会发生无限重新渲染。

有什么想法吗?

代码的完整版本是:

注意:如果没有去抖动,该错误仍然会发生,或者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>
  );
}
Run Code Online (Sandbox Code Playgroud)

Kil*_*man 5

您遇到的问题是 fetcher 在整个获取过程中都会更新。这会导致您的效果重新运行,并且由于您load再次调用,因此它正在重复该循环。

您应该检查一下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])
Run Code Online (Sandbox Code Playgroud)

https://remix.run/docs/en/v1/api/remix#usefetcher