You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免React自定义hook在组件首次渲染时发起请求?

解决方案:手动触发请求,避免首次渲染自动调用

你的问题核心在于当前的useFetchLink会在linkToShorten变化时自动发起请求,包括首次渲染时nextLink初始值(undefined)触发的请求。要避免这种情况,最直接的方法是把hook改成手动触发模式,让组件完全控制请求时机。

修改自定义hook:返回触发函数

调整useFetchLink,去掉自动执行的useEffect,而是把请求函数返回给组件,由组件决定什么时候调用:

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

  const fetchLink = async (linkToShorten) => {
    if (!linkToShorten) return; // 空值不发起请求
    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);
        setError(""); // 成功时清空错误
      } else {
        throw response.status;
      }
    } catch (err) {
      setError(err);
      setShortLink(""); // 失败时清空短链接
    } finally {
      setLoading(false);
    }
  };

  return { shortLink, loading, error, fetchLink };
};

修改组件:在点击时触发请求

调整LinkShortener组件,在点击按钮时调用hook返回的fetchLink,并在请求完成后更新链接数组:

export default function LinkShortener({ setLinkArr }) {
  const inputRef = useRef(null);
  const { shortLink, loading, error, fetchLink } = useFetchLink();

  const handleClick = async () => {
    const inputValue = inputRef.current.value.trim();
    if (!inputValue) return; // 空输入不处理
    
    await fetchLink(inputValue);
    
    // 请求成功后更新链接数组
    if (shortLink) {
      setLinkArr((prev) => [
        ...prev,
        {
          id: prev.length === 0 ? 1 : prev[prev.length - 1].id + 1,
          long: inputValue,
          short: shortLink,
        },
      ]);
      inputRef.current.value = "";
    }
  };

  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中自动触发的useEffect,请求完全由组件的点击事件控制,首次渲染时不会发起任何请求。
  • 把linkToShorten作为参数传给fetchLink,而不是依赖hook的入参触发,避免了初始值导致的误触发。
  • 保留了hook内部的状态管理(loading、shortLink、error),组件依然可以获取请求状态。

额外优化点

  • 在fetchLink里增加空值判断,避免无效请求。
  • 请求成功/失败时分别清空错误/短链接状态,避免状态残留。

内容的提问来源于stack exchange,提问作者user19786344

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 16:40:27