React路由器重定向导致useEffect触发两次

React router redirection causes useEffect to trigger twice

我的路线定义如下:

<Route path={`list`} element={<ListPage />}>
  <Route path={`sidePanel1`} element={<SidePanel1 />} />
  <Route path={`sidePanel2`} element={<SidePanel2 />} />
  <Route index element={<Navigate to={`sidePanel1`} replace />}/>
</Route>

因此,当输入 /list 时,它将被重定向到 /list/sidePanel1

ListPage 组件中我有这个:

const ListPage = (): JSX.Element => {
  const [data, setData] = useState<ListDto[]>([]);

  const location = useLocation();

  useEffect(() => {

    getList()
      .then(response => {
        setData(response.data);
      })
      .catch(() => {
        setIsLoading(false);
      });
  }, [location]);
  return (
    <ListTable data={data}/>
    <SidePanelStyles>
       <Outlet />
    </SidePanelStyles>
  );
};

所以,我的问题是,每当我键入 /list/ 时,useEffect 都会触发,因为位置已更改,然后在重定向到 /list/sidePanel1.[=17 时会第二次触发=]

我希望它仅在我被重定向后触发。

我该如何解决这个问题?

与其重定向和渲染两次,不如在索引路由上也渲染 SidePanel1 组件。

示例:

<Route path="list" element={<ListPage />}>
  <Route index element={<SidePanel1 />} />
  <Route path="sidePanel1" element={<SidePanel1 />} />
  <Route path="sidePanel2" element={<SidePanel2 />} />
</Route>

一个 general-purpose 仅对快速更改序列中的最后更改做出反应的解决方案是使用“去抖动”。

即触发效果和调用 getList 之间的延迟,因此如果在延迟完成之前再次触发效果,挂起的调用将被取消。

function useDebouncedEffect(delay, effect, triggerParams) {
  useEffect(() => {
    const timeout = setTimeout(f, delay)
    return () => clearTimeout(timeout)
  }, triggerParams)
}

useDebouncedEffect(300, () => {
  getList()
    .then(response => {
      setData(response.data);
    })
    .catch(() => {
      setIsLoading(false);
    });
  }, [location]);