简体   繁体   English

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

[英]React router redirection causes useEffect to trigger twice

I have a route defined as following:我的路线定义如下:

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

So, when /list is typed it will be redirected to /list/sidePanel1 .因此,当输入/list时,它将被重定向到/list/sidePanel1

in the ListPage component I have this: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>
  );
};

So, my problem is that whenever I type /list/ the useEffect will trigger since the location has changed, and then it will trigger for the second time when redirected to /list/sidePanel1 .所以,我的问题是,每当我键入/list/时,useEffect 都会触发,因为位置已经改变,然后它会在重定向到/list/sidePanel1时第二次触发。

I want it to only be triggered after I get redirected.我希望它仅在我被重定向后触发。

How can I solve this ?我该如何解决这个问题?

Instead of redirecting and rendering twice, just render SidePanel1 component on the index route as well.无需重定向和渲染两次,只需在索引路由上渲染SidePanel1组件即可。

Example:例子:

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

One general-purpose solution to only react to the last change in a quick sequence of changes is to use a "debounce".一种仅对快速更改序列中的最后一个更改做出反应的通用解决方案是使用“去抖动”。

Ie a delay between when the effect is triggered and when getList is called, so that if the effect is triggered again before the delay is finished, the pending call will be canceled.即在触发效果和调用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]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM