基于条件的默认渲染
Default render based on conditions
我正在设计一个基本的 login/sign up 界面。登录和注册 UI 驻留在它们自己的组件中,并且每个都包含一个 link 到彼此(使用 <Link to>
以防用户在显示注册时已经有一个帐户,或者想要创建显示登录时的帐户)。
我的结构如下:
index.tsx
ReactDOM.render(
<MemoryRouter>
<Routes>
<Route path="/" element={<App />} >
<Route path="signup" element={<Signup />} />
<Route path="login" element={<Login />} />
</Route>
</Routes >
</MemoryRouter >,
document.getElementById('root')
);
App.tsx
function App() {
return (
<div className="App">
<UserControl />
<Outlet />
</div>
);
}
UserControl.tsx
function UserControl() {
///snip unrelated code
if (!isLoggedIn && !userHasNeverLoggedInBefore) {
return (<Signup />)
} else if (!isLoggedIn) {
return (<Login />)
} else {
return (<Functionality />
)
}
}
打开“/”时,我想决定是显示登录、注册还是功能。我也想 links 在登录和注册中互相。
用我目前的方法,我看到 UI 两次 - 我假设一个来自 App.tsx 中的 <UserControl>
,另一个来自 <Outlet>
.如何有条件地只渲染一次?
我正在使用 React Router 6。
您正在渲染它们两次。我建议在 UserControl
中使用重定向将用户推送到呈现正确 Login
或 Signup
组件的正确路径。
示例:
function UserControl() {
// ... snip unrelated code
if (!isLoggedIn) {
return (
<Navigate
to={userHasNeverLoggedInBefore ? "/login" : "/signup"}
replace
/>
);
}
return <Functionality />;
}
更新
This seems to render the first component correctly, however now the
links between login and sign up are broken (clicking does nothing).
For context, this is how I set up links in the component : <Link to="/signup">Sign up</Link>
and similarly for the sign up component.
我认为这里的问题是您正在创建一个 quasi-AuthWrapper 组件,该组件重定向到它作为子项呈现的路由。当用我的解决方案测试你的代码时,它变成了一个无限渲染循环。完全不理想。
然后我建议将 UserControl
转换为 full-blown AuthWrapper 组件。
将 <Functionality />
替换为 <Outlet />
组件。
function UserControl() {
// ... snip unrelated code
if (!isLoggedIn) {
return (
<Navigate
to={userHasNeverLoggedInBefore ? "/login" : "/signup"}
replace
/>
);
}
return <Outlet />;
}
将路线移至 App
。使用UserControl
组件作为布局组件保护路由渲染<Functionality />
。将登录和注册路由 移出身份验证包装器的 。
function App() {
return (
<div className="App">
<Routes>
<Route element={<UserControl />}>
<Route path="/" element={<Functionality />} />
</Route>
<Route path="/signup" element={<Signup />} />
<Route path="/login" element={<Login />} />
</Routes>
</div>
);
}
我正在设计一个基本的 login/sign up 界面。登录和注册 UI 驻留在它们自己的组件中,并且每个都包含一个 link 到彼此(使用 <Link to>
以防用户在显示注册时已经有一个帐户,或者想要创建显示登录时的帐户)。
我的结构如下:
index.tsx
ReactDOM.render(
<MemoryRouter>
<Routes>
<Route path="/" element={<App />} >
<Route path="signup" element={<Signup />} />
<Route path="login" element={<Login />} />
</Route>
</Routes >
</MemoryRouter >,
document.getElementById('root')
);
App.tsx
function App() {
return (
<div className="App">
<UserControl />
<Outlet />
</div>
);
}
UserControl.tsx
function UserControl() {
///snip unrelated code
if (!isLoggedIn && !userHasNeverLoggedInBefore) {
return (<Signup />)
} else if (!isLoggedIn) {
return (<Login />)
} else {
return (<Functionality />
)
}
}
打开“/”时,我想决定是显示登录、注册还是功能。我也想 links 在登录和注册中互相。
用我目前的方法,我看到 UI 两次 - 我假设一个来自 App.tsx 中的 <UserControl>
,另一个来自 <Outlet>
.如何有条件地只渲染一次?
我正在使用 React Router 6。
您正在渲染它们两次。我建议在 UserControl
中使用重定向将用户推送到呈现正确 Login
或 Signup
组件的正确路径。
示例:
function UserControl() {
// ... snip unrelated code
if (!isLoggedIn) {
return (
<Navigate
to={userHasNeverLoggedInBefore ? "/login" : "/signup"}
replace
/>
);
}
return <Functionality />;
}
更新
This seems to render the first component correctly, however now the links between login and sign up are broken (clicking does nothing). For context, this is how I set up links in the component :
<Link to="/signup">Sign up</Link>
and similarly for the sign up component.
我认为这里的问题是您正在创建一个 quasi-AuthWrapper 组件,该组件重定向到它作为子项呈现的路由。当用我的解决方案测试你的代码时,它变成了一个无限渲染循环。完全不理想。
然后我建议将 UserControl
转换为 full-blown AuthWrapper 组件。
将
<Functionality />
替换为<Outlet />
组件。function UserControl() { // ... snip unrelated code if (!isLoggedIn) { return ( <Navigate to={userHasNeverLoggedInBefore ? "/login" : "/signup"} replace /> ); } return <Outlet />; }
将路线移至
App
。使用UserControl
组件作为布局组件保护路由渲染<Functionality />
。将登录和注册路由 移出身份验证包装器的 。function App() { return ( <div className="App"> <Routes> <Route element={<UserControl />}> <Route path="/" element={<Functionality />} /> </Route> <Route path="/signup" element={<Signup />} /> <Route path="/login" element={<Login />} /> </Routes> </div> ); }