你可以如何将React路由添加到主布局中的内容部分?

huangapple go评论81阅读模式
英文:

How can I add React router to the content section in the main layout?

问题

function MainLayout() {
    // ... (your existing code)

    return (
        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
            {isLoading ? (
                <Spin size="large" />
            ) : (
                <Layout
                    style={{
                        minHeight: "100vh",
                    }}
                >
                    {/* ... (your existing code) */}
                    
                    {/* Remove the following line to prevent the infinite loop */}
                    {/* <AppRoutes/> PROBLEM HERE */}
                    
                    {/* ... (your existing code) */}
                </Layout>
            )}
        </div>
    );
}

Note: I've commented out the problematic line <AppRoutes/> as you requested.

英文:

I am developing application using React redux-toolkit. I added the route schema, and then I get the 'wow' error saying the page can't respond when it probably goes into an infinite loop. I have a MainLayout and I want to go to the content part of it by clicking the properties of the layout in the side menu. For example, the page that gives the list of registered cities when I click, the page that gives the names of the countries. I want to give these pages in the content section of the main layout. That's why I need to give you the route diagram that I have prepared. Since I also wrap routes in the app, I think it goes into an infinite loop because it wraps the route part twice, but I don't know how I can solve it. I need help.

function AppRoutes() {
return (
&lt;Routes&gt;
&lt;Route element={&lt;PrivateRoutes&gt;&lt;MainLayout/&gt;&lt;/PrivateRoutes&gt;} path=&quot;/&quot;&gt;
{/* &lt;Route element={&lt;MainLayout/&gt;} path=&quot;/&quot;/&gt; */}
&lt;/Route&gt;
&lt;Route element={&lt;Login/&gt;} path=&quot;/login&quot;/&gt;
&lt;Route element={&lt;CityList/&gt;} path=&quot;/city/list&quot;/&gt;
&lt;Route element={&lt;Register/&gt;} path=&quot;/register&quot;/&gt;
&lt;Route element={&lt;ActivateEmail/&gt;} path=&quot;/account/activate&quot;/&gt;
&lt;Route element={&lt;NoMatch/&gt;} path=&quot;*&quot;/&gt;
&lt;/Routes&gt;
)
}
export default AppRoutes
const PrivateRoutes = ({children}) =&gt; {
const {userToken } = useSelector((state) =&gt; state.auth);
if(!userToken){
return &lt;Navigate to=&quot;/login&quot;/&gt;
}else{
return children;
}
}
export default PrivateRoutes;
function App() {
const [locale, setLocale] = useState(&#39;tr&#39;);
return (
&lt;IntlProvider locale={locale} messages={messages[locale]}&gt;
&lt;AppRoutes/&gt;
&lt;/IntlProvider&gt;
);
};
export default App
import { UserOutlined, FileOutlined, SettingOutlined, DownOutlined, LogoutOutlined } from &quot;@ant-design/icons&quot;;
import { Breadcrumb, Layout, Menu, theme, Input, Space, Card, Button, Dropdown, message, Tag, Spin, Row, Col, Form } from &quot;antd&quot;;
import { useState, useEffect } from &quot;react&quot;;
import { RiLockPasswordLine } from &#39;react-icons/ri&#39;
import {AiOutlineMenu} from &#39;react-icons/ai&#39;
import { useDispatch, useSelector } from &quot;react-redux&quot;;
import { getUserbyId, signOut } from &quot;../utils/api.service&quot;;
import { useNavigate } from &#39;react-router-dom&#39;;
import { getTokenSub } from &#39;../utils/HelperFunctions&#39;;
import { getUser, userInfo } from &#39;../types/user&#39;;
import { useIntl } from &quot;react-intl&quot;;
import AppRouteList from &quot;../routes/AppRouteList&quot;;
import FormButton from &quot;../components/FormButton&quot;;
import InputDisableText from &quot;../components/InputDisableText&quot;;
import AppRoutes, { RouteApp } from &quot;../routes/AppRoutes&quot;;
const { Header, Content, Footer, Sider } = Layout;
export function MainLayout() {
const {userToken } = useSelector((state) =&gt; state.auth);
const intl = useIntl();
const navigate = useNavigate();
const menuItemClick = (e) =&gt; {
switch(e.key){
case &quot;menu_city_list&quot;:
navigate(&quot;/city/list&quot;)
break;
default:
break;
}
}
function getItem(label, key, icon, children) {
return {
key,
icon,
children,
label,
};
}
const items = [
getItem(&quot;Faturalar&quot;, &quot;sub1&quot;, &lt;FileOutlined /&gt;, [
getItem(&quot;Team 1&quot;, &quot;1&quot;),
getItem(&quot;Team 2&quot;, &quot;2&quot;),
]),
getItem(&quot;Sistem Ayarları&quot;, &quot;sub2&quot;, &lt;SettingOutlined /&gt;, [
getItem(&quot;&#220;lkeler&quot;, &quot;5&quot;),
getItem(intl.formatMessage({id:&quot;menu_city_list&quot;}),&quot;menu_city_list&quot;,&lt;AiOutlineMenu/&gt;),
getItem(&quot;Client&quot;, &quot;7&quot;),
getItem(&quot;Tom&quot;, &quot;8&quot;),
getItem(&quot;Bill&quot;, &quot;9&quot;),
getItem(&quot;Alex&quot;, &quot;10&quot;),
getItem(&quot;Tom&quot;, &quot;11&quot;),
// getItem(&quot;Bill&quot;, &quot;12&quot;),
// getItem(&quot;Alex&quot;, &quot;13&quot;),
// getItem(&quot;Tom&quot;, &quot;14&quot;),
getItem(&quot;Genel Ayarlar&quot;, &quot;15&quot;),
]),
getItem(&quot;Hesabım&quot;, &quot;sub3&quot;, &lt;UserOutlined /&gt;, [
getItem(&quot;Hesabım&quot;, &quot;3&quot;),
getItem(&quot;Oturum Kapat&quot;, &quot;4&quot;),
]),
];
const handleButtonClick = (e) =&gt; {
message.info(&#39;Click on left button.&#39;);
console.log(&#39;click left button&#39;, e);
};
const handleMenuClick = (e) =&gt; {
message.info(&#39;Click on menu item.&#39;);
console.log(&#39;click&#39;, e);
};
const [isLoading, setIsLoading] = useState(false);
const token = localStorage.getItem(&#39;userToken&#39;);
const sub = getTokenSub(token);
const dispatch = useDispatch();
getUser.Id = sub
useEffect(() =&gt; {
dispatch(getUserbyId(getUser)).then((result) =&gt; {            
userInfo.id = result.payload.id
userInfo.clientId = result.payload.clientId
userInfo.clientName = result.payload.clientName
userInfo.email = result.payload.email
userInfo.firstName = result.payload.firstName
userInfo.lastName = result.payload.lastName
userInfo.isActive = result.payload.isActive
userInfo.normalizedEmail = result.payload.normalizedEmail
userInfo.userName = result.payload.userName
userInfo.passwordChangeTime = result.payload.passwordChangeTime
});
}, [dispatch, getUser])
useEffect(() =&gt; {
setIsLoading(true);
setTimeout(() =&gt; {
setIsLoading(false);
}, 1000);
}, []);
const handleLogout = () =&gt; {
dispatch(signOut())
};
const itemsDropDown = [
{
label: &#39;Hesabım&#39;,
key: &#39;100&#39;,
icon: &lt;UserOutlined /&gt;,
},
{
label: &#39;Şifremi Değiştir&#39;,
key: &#39;200&#39;,
icon: &lt;RiLockPasswordLine /&gt;,
},
{
label: &#39;Oturum Kapat&#39;,
key: &#39;400&#39;,
icon: &lt;LogoutOutlined /&gt;,
danger: true,
onClick: handleLogout
},
];
const menuProps = {
items: itemsDropDown,
// onClick: handleMenuClick,
};
const [collapsed, setCollapsed] = useState(false);
const {
token: { colorBgContainer },
} = theme.useToken();
return (
&lt;div style={{ display: &#39;flex&#39;, justifyContent: &#39;center&#39;, alignItems: &#39;center&#39;, height: &#39;100vh&#39; }}&gt;
{isLoading ? (
&lt;Spin size=&quot;large&quot; /&gt;
) : (
&lt;Layout
style={{
minHeight: &quot;100vh&quot;,
}}
&gt;
{console.log(&quot;user ınfo&quot;, userToken)}
&lt;Sider
collapsible
collapsed={collapsed}
onCollapse={(value) =&gt; setCollapsed(value)}
&gt;
&lt;div
style={{
height: 32,
margin: 16,
background: &quot;rgba(255, 255, 255, 0.8)&quot;,
}}
&gt;
&lt;/div&gt;
&lt;Menu
theme=&quot;dark&quot;
defaultSelectedKeys={[&quot;1&quot;]}
mode=&quot;inline&quot;
items={items}
onClick={menuItemClick}
/&gt;
&lt;/Sider&gt;
&lt;Layout className=&quot;site-layout&quot;&gt;
&lt;Header
style={{
padding: 0,
background: colorBgContainer,
}}
&gt;
&lt;/Header&gt;
&lt;Content
style={{
margin: &quot;0 16px&quot;,
}}
&gt;
{/* &lt;AppRoutes/&gt; PROBLEM HERE */} 
&lt;/div&gt;
&lt;/Content&gt;
&lt;Footer
&lt;/Footer&gt;
&lt;/Layout&gt;
&lt;/Layout&gt;
)}
&lt;/div&gt;
);
}

When I open the AppRoutes component in the comments line in the content on the main layout page, it enters an endless loop and the browser stops responding and gives an error.

Web Browser
你可以如何将React路由添加到主布局中的内容部分?

你可以如何将React路由添加到主布局中的内容部分?

答案1

得分: 0

AppRoutes 渲染 MainLayout,当渲染另一个 AppRoutes 时,再次渲染另一个 MainLayout... 你看到问题了吗?这会通过无限递归创建一个“渲染循环”。

我怀疑你的意图是让 MainLayout 渲染一个用作布局路由的 Outlet 组件,它可能作为布局路由渲染。

如果你打算让 MainLayout 成为所有路由的布局路由组件,那么它应该包装所有路由。PrivateRoute 组件也应该转换为布局路由组件,以便它可以包装应该受保护的所有路由。

PrivateRoutes 组件如下:

import { Navigate, Outlet } from 'react-router-dom';

const PrivateRoutes = () => {
  const { userToken } = useSelector((state) => state.auth);

  return userToken ? <Outlet /> : <Navigate to="/login" replace />;
}

AppRoutes 组件如下:

function AppRoutes() {
  return (
    <Routes>
      <Route element={<Login />} path="/login" />
      <Route element={<Register />} path="/register" />
      {/* ... 其他非主布局路由 */}

      <Route element={<MainLayout />}>
        <Route element={<ActivateEmail />} path="/account/activate" />
        {/* ... 其他不受保护的路由 */}

        <Route element={<PrivateRoutes />}>
          <Route element={<CityList />} path="/city/list" />
          {/* ... 其他受保护的路由 */}
        </Route>

        <Route element={<NoMatch />} path="*" />
        {/* ... 其他主布局路由 */}
      </Route>
    </Routes>
  )
}
英文:

AppRoutes renders MainLayout which when rendering another AppRoutes renders another MainLayout... do you see the problem? This creates a "render loop" by infinite recursion.

I suspect you meant for MainLayout to render an Outlet component for nested routes it may be rendering as a layout route.

import { Outlet } from &#39;react-router-dom&#39;;

...

export function MainLayout() {
  ...

  return (
    &lt;div style={{ .... }}&gt;
      {isLoading ? (
        &lt;Spin size=&quot;large&quot; /&gt;
      ) : (
        &lt;Layout style={{ .... }}&gt;
          ...
          &lt;Layout className=&quot;site-layout&quot;&gt;
            &lt;Header style={{ .... }} /&gt;
            &lt;Content style={{ .... }}&gt;
              &lt;Outlet /&gt; // &lt;-- for nested route content
            &lt;/Content&gt;
            &lt;Footer /&gt;
          &lt;/Layout&gt;
        &lt;/Layout&gt;
      )}
    &lt;/div&gt;
  );
}

If you are intending for MainLayout to be a layout route component for all routes then it should wrap all routes. The PrivateRoute component should also be converted to a layout route component so it can wrap all routes that should be protected.

import { Navigate, Outlet } from &#39;react-router-dom&#39;;

const PrivateRoutes = () =&gt; {
  const { userToken } = useSelector((state) =&gt; state.auth);

  return userToken ? &lt;Outlet /&gt; : &lt;Navigate to=&quot;/login&quot; replace /&gt;;
}
function AppRoutes() {
  return (
    &lt;Routes&gt;
      &lt;Route element={&lt;Login /&gt;} path=&quot;/login&quot; /&gt;
      &lt;Route element={&lt;Register /&gt;} path=&quot;/register&quot; /&gt;
      {/* ... other non-main-layout routes */}
        
      &lt;Route element={&lt;MainLayout /&gt;}&gt;
        &lt;Route element={&lt;ActivateEmail /&gt;} path=&quot;/account/activate&quot; /&gt;
        {/* ... other unprotected routes */}

        &lt;Route element={&lt;PrivateRoutes /&gt;}&gt;
          &lt;Route element={&lt;CityList /&gt;} path=&quot;/city/list&quot; /&gt;
          {/* ... other protected routes */}
        &lt;/Route&gt;

        &lt;Route element={&lt;NoMatch /&gt;} path=&quot;*&quot; /&gt;
        {/* ... other main-layout routes */}
      &lt;/Route&gt;
    &lt;/Routes&gt;
  )
}

huangapple
  • 本文由 发表于 2023年3月31日 04:02:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892510.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定