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

如何条件性运行React自定义Hook?解决误跳转编辑页问题

解决自定义Hook条件跳转问题

问题根源

你当前的useDuplicateItem在组件渲染时就直接调用了useRedirectEditPage,导致这个跳转监听Hook只要组件存在就会生效。删除操作会更新saveResponses状态,触发useRedirectEditPage里的useEffect,进而执行跳转逻辑,这就是删除时也会跳转到编辑页的原因。

解决方案

下面提供两种可行的解决思路,你可以根据项目需求选择:


方案一:给跳转Hook添加启用开关

修改useRedirectEditPage,增加一个enabled参数控制监听逻辑是否生效:

export default function useRedirectEditPage(slug: string, enabled: boolean = true) {
  const { saveResponses, setSaveResponses, setHeaderStates } = useAdminContext();
  const router = useRouter();

  useEffect(() => {
    // 未启用时直接退出,不执行监听逻辑
    if (!enabled) return;

    const statusCodes: number[] = [];
    let id;

    saveResponses.forEach((value) => {
      statusCodes.push(value?.status);
      id = value?.id;
    });

    if (statusCodes.length && id) {
      if (statusCodes.includes(404)) {
        setHeaderStates((prev) => ({
          ...prev,
          canBeSaved: false,
        }));
      } else {
        router.push(`/admin/${slug}/edit/${id}`);
        setSaveResponses(new Map());
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [saveResponses, router, setSaveResponses, enabled]);
}

接着修改useDuplicateItem,用状态控制跳转Hook的启用,只有执行复制操作时才开启监听:

export default function useDuplicateItem(url: string) {
  const { sendRequest: duplicate } = useHttpRequest();
  const [isDuplicating, setIsDuplicating] = useState(false);

  const duplicateItem = useCallback(
    (data) => {
      setIsDuplicating(true);
      duplicate([
        {
          url: `/api/server/${url}`,
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          data,
        },
      ]);
    },
    [duplicate, url]
  );

  // 仅在复制操作执行后启用跳转监听
  useRedirectEditPage(url, isDuplicating);

  return duplicateItem;
}

方案二:将跳转逻辑绑定到复制请求回调

如果useHttpRequest的sendRequest返回Promise,可以直接在复制请求完成后处理跳转,无需单独的监听Hook:

export default function useDuplicateItem(url: string) {
  const { sendRequest: duplicate } = useHttpRequest();
  const { saveResponses, setSaveResponses, setHeaderStates } = useAdminContext();
  const router = useRouter();

  const duplicateItem = useCallback(
    async (data) => {
      // 执行复制请求
      await duplicate([
        {
          url: `/api/server/${url}`,
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          data,
        },
      ]);

      // 请求完成后处理跳转逻辑
      const statusCodes: number[] = [];
      let id;

      saveResponses.forEach((value) => {
        statusCodes.push(value?.status);
        id = value?.id;
      });

      if (statusCodes.length && id) {
        if (statusCodes.includes(404)) {
          setHeaderStates((prev) => ({
            ...prev,
            canBeSaved: false,
          }));
        } else {
          router.push(`/admin/${url}/edit/${id}`);
          setSaveResponses(new Map());
        }
      }
    },
    [duplicate, url, saveResponses, router, setSaveResponses, setHeaderStates]
  );

  return duplicateItem;
}

方案对比

  • 方案一保留了useRedirectEditPage的复用性,适合需要在多个场景复用跳转逻辑的情况。
  • 方案二更直接,把跳转逻辑和复制操作强绑定,避免了全局监听带来的意外触发,适合只在复制场景使用跳转的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:40:26