当多个链接路由使用同一组件时如何避免重新初始化组件
How to avoid re-initializing component when multiple linked routes use same component
我有一个 react-router-dom 组件,它在 v5 中运行良好,我已经升级到 v6。在下面的路由器结构中,我有一个通过不同路由访问的组件。此视图具有播放功能,可在播放停止时更新 URL,从而产生 foo/<fooId>/<time>
url 结构,以及 link 列表中带有 [= 的内容的方法13=]。这两个呈现相同的组件,根据需要使用参数并且可以处理两个入口点。
我在迁移到 v6 后遇到的问题是,如果从 foo/<fooId>/<time>
切换到 bar/<barId>
或反之亦然,它会刷新。如果我在 foo/<foodId>/time
上单击 link 到 bar/<barId>
,也会发生同样的情况。它是同一个组件,过去只是更新了浏览器URL(以前使用history.pushState
,现在使用navigate
(来自useNavigate
),我尝试添加一个替换参数等,但它仍然会重新安装整个组件。
我怎样才能避免这种情况?只能想着重新整理一下页面了,书签一堆,会很不爽,哈哈。
<Route
path="/foo"
element={<AuthedRoute authState={authState} element={<Bar />} />}
>
<Route
path=":fooId"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
<Route
path=":fooId/:timestamp"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
</Route>
<Route path="/bar">
<Route
path=":barId"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
</Route>
授权路线:
function AuthedRoute({ authState, element }) {
const location = useLocation()
const { isLoggedIn } = authState
return isLoggedIn ? (
element
) : (
<Navigate
to="/login"
state={{
from: location,
}}
/>
)
}
与示例结构相似here
开枪,好吧,我没有注意到你嵌套了“/foo”和“/bar”路由。这改变了一些事情。我能够重现在“/foo”和“/bar”路由之间切换的问题。我仍然建议将 AuthedRoute
转换为布局组件并为要保护的嵌套路由呈现 Outlet
。
function AuthedRoute({ authState }) {
const location = useLocation();
const { isLoggedIn } = authState;
return isLoggedIn ? (
<Outlet />
) : (
<Navigate
to="/login"
state={{
from: location
}}
/>
);
}
接下来是 configure/structure 您的路线,以便正确嵌套。以下结构似乎如您所料。
<Routes>
<Route element={<AuthedRoute authState={authState} />}>
<Route path="/foo/*">
<Route index element={<Bar />} />
<Route path=":fooId" element={<Bar />} />
<Route path=":fooId/:timestamp" element={<Bar />} />
</Route>
<Route path="/bar/*">
<Route path=":barId" element={<Bar />} />
</Route>
</Route>
<Route path="/login" element={<Login /* auth props? */ />} />
</Routes>
用于测试 Bar
组件何时安装与渲染(一个 id
道具被传递给每个组件以识别它们):
const Bar = ({ id }) => {
useEffect(() => {
console.log("Bar MOUNTED!!", { id });
}, []);
useEffect(() => {
console.log("Bar Rendered!!", { id });
}, [id]);
return <h1>Bar</h1>;
};
通过身份验证后,使用链接在所有不同的路由之间导航,并注意“已安装”与“已渲染”记录的时间。
这是我的 运行 codesandbox:
我有一个 react-router-dom 组件,它在 v5 中运行良好,我已经升级到 v6。在下面的路由器结构中,我有一个通过不同路由访问的组件。此视图具有播放功能,可在播放停止时更新 URL,从而产生 foo/<fooId>/<time>
url 结构,以及 link 列表中带有 [= 的内容的方法13=]。这两个呈现相同的组件,根据需要使用参数并且可以处理两个入口点。
我在迁移到 v6 后遇到的问题是,如果从 foo/<fooId>/<time>
切换到 bar/<barId>
或反之亦然,它会刷新。如果我在 foo/<foodId>/time
上单击 link 到 bar/<barId>
,也会发生同样的情况。它是同一个组件,过去只是更新了浏览器URL(以前使用history.pushState
,现在使用navigate
(来自useNavigate
),我尝试添加一个替换参数等,但它仍然会重新安装整个组件。
我怎样才能避免这种情况?只能想着重新整理一下页面了,书签一堆,会很不爽,哈哈。
<Route
path="/foo"
element={<AuthedRoute authState={authState} element={<Bar />} />}
>
<Route
path=":fooId"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
<Route
path=":fooId/:timestamp"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
</Route>
<Route path="/bar">
<Route
path=":barId"
element={<AuthedRoute authState={authState} element={<Bar />} />}
/>
</Route>
授权路线:
function AuthedRoute({ authState, element }) {
const location = useLocation()
const { isLoggedIn } = authState
return isLoggedIn ? (
element
) : (
<Navigate
to="/login"
state={{
from: location,
}}
/>
)
}
与示例结构相似here
开枪,好吧,我没有注意到你嵌套了“/foo”和“/bar”路由。这改变了一些事情。我能够重现在“/foo”和“/bar”路由之间切换的问题。我仍然建议将 AuthedRoute
转换为布局组件并为要保护的嵌套路由呈现 Outlet
。
function AuthedRoute({ authState }) {
const location = useLocation();
const { isLoggedIn } = authState;
return isLoggedIn ? (
<Outlet />
) : (
<Navigate
to="/login"
state={{
from: location
}}
/>
);
}
接下来是 configure/structure 您的路线,以便正确嵌套。以下结构似乎如您所料。
<Routes>
<Route element={<AuthedRoute authState={authState} />}>
<Route path="/foo/*">
<Route index element={<Bar />} />
<Route path=":fooId" element={<Bar />} />
<Route path=":fooId/:timestamp" element={<Bar />} />
</Route>
<Route path="/bar/*">
<Route path=":barId" element={<Bar />} />
</Route>
</Route>
<Route path="/login" element={<Login /* auth props? */ />} />
</Routes>
用于测试 Bar
组件何时安装与渲染(一个 id
道具被传递给每个组件以识别它们):
const Bar = ({ id }) => {
useEffect(() => {
console.log("Bar MOUNTED!!", { id });
}, []);
useEffect(() => {
console.log("Bar Rendered!!", { id });
}, [id]);
return <h1>Bar</h1>;
};
通过身份验证后,使用链接在所有不同的路由之间导航,并注意“已安装”与“已渲染”记录的时间。
这是我的 运行 codesandbox: