【问题标题】:Stop invoking custom hook on first render在第一次渲染时停止调用自定义钩子
【发布时间】:2022-09-23 16:04:16
【问题描述】:

我最近开始享受自定义钩子的乐趣。我主要使用它们从 api 获取。问题是,因为我不能真正将 useFetchLink 放在函数或 useEffect 中,所以我不知道如何防止它在网站首次呈现后获取。我可以把一些 ifs 放在钩子里,但没有其他方法吗?

***component*** 

export default function LinkShortener({ setLinkArr }) {
  const [nextLink, setNextLink] = useState();
  const inputRef = useRef(null);

  const handleClick = () => {
    setNextLink(inputRef.current.value);
  };

  const { shortLink, loading, error } = useFetchLink(nextLink);

  useEffect(() => {
    setLinkArr((prev) => [
      ...prev,
      {
        id: prev.length === 0 ? 1 : prev[prev.length - 1].id + 1,
        long: nextLink,
        short: shortLink,
      },
    ]);
    inputRef.current.value = \"\";
  }, [shortLink, error]);

  return (
    <LinkShortenerContainer>
      <InputContainer>
        <LinkInput ref={inputRef} type=\"text\" />
      </InputContainer>
      <Button
        size={buttonSize.medium}
        text={
          loading ? (
            <Loader />
          ) : (
            <FormattedMessage
              id=\"linkShortener.shortenItBtn\"
              defaultMessage=\"Shorten It !\"
            />
          )
        }
        onClick={handleClick}
      ></Button>
    </LinkShortenerContainer>
  );
}
***hook***
const useFetchLink = (linkToShorten) => {
  const [shortLink, setShortLink] = useState(\"\");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(\"\");

  const fetchLink = async () => {
    setLoading(true);
    try {
      const response = await fetch(
        `https://api.shrtco.de/v2/shorten?url=${linkToShorten}`
      );
      if (response.ok) {
        const data = await response.json();
        setShortLink(data.result.short_link);
      } else {
        throw response.status;
      }
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchLink(linkToShorten);
  }, [linkToShorten]);

  const value = { shortLink, loading, error };
  return value;
};```
  • 钩子中的if 正是您想要的。
  • 如果linkToShorten 不改变效果不会触发
  • 但是 linkToShorten 提供了 nextLink 状态,并且它在第一次渲染时设置为 \"\"
  • @GiorgiMoniava 说了什么,但是通过查看 JSX 代码来了解示例的整个流程会很有帮助。你可以在 CodeSandbox、StackBlitz 或类似的东西中创建它。
  • @AglecikNaplecik “第一次渲染”是什么意思?我敢打赌,问题隐藏在代码的其余部分中。

标签: reactjs react-hooks


【解决方案1】:

为什么不直接使用fetchLink 函数并在组件内部需要时调用它?我会在没有useEffect 的情况下以这种方式更改钩子

const useFetchLink = (linkToShorten) => {
  const [shortLink, setShortLink] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const fetchLink = async () => {
    setLoading(true);
    try {
      const response = await fetch(
        `https://api.shrtco.de/v2/shorten?url=${linkToShorten}`
      );
      if (response.ok) {
        const data = await response.json();
        setShortLink(data.result.short_link);
      } else {
        throw response.status;
      }
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  };

  const value = { shortLink, loading, error, fetchLink };
  return value;
};

【讨论】:

    【解决方案2】:

    一般来说-避免useEffect运行第一次渲染的标准方法是使用boolean ref 初始化false,并在第一次渲染后切换到true-见answer

    但是,在您的情况下,如果linkToShorten 为空,即使它不是第一次渲染,您也不想调用该函数,因此请在useEffect 内使用if

    const useFetchLink = (linkToShorten) => {
      const [shortLink, setShortLink] = useState("");
      const [loading, setLoading] = useState(false);
      const [error, setError] = useState("");
    
      const fetchLink = useCallback(async (linkToShorten) => {
        setLoading(true);
        try {
          const response = await fetch(
            `https://api.shrtco.de/v2/shorten?url=${linkToShorten}`
          );
          if (response.ok) {
            const data = await response.json();
            setShortLink(data.result.short_link);
          } else {
            throw response.status;
          }
        } catch (err) {
          setError(err);
        } finally {
          setLoading(false);
        }
      }, []);
    
      useEffect(() => {
        if(linkToShorten) fetchLink(linkToShorten);
      }, [fetchLink, linkToShorten]);
    
      const value = { shortLink, loading, error };
      return value;
    };
    

    【讨论】:

      猜你喜欢
      • 2021-11-02
      • 2020-02-28
      • 1970-01-01
      • 2021-11-22
      • 2023-01-14
      • 2022-01-10
      • 2019-12-24
      • 2022-07-18
      • 2019-10-02
      相关资源
      最近更新 更多