I have a question about displaying or routing components in React.
I set up a homepage layout
with a title
, left
menu, and a content
section. The idea is to have a page where you only need to change the main content section.
I'm wondering if this is a good approach and if I have to use a router or just a hook to do this.
In what I did, I just used the useState
hook to set the component to be displayed and didn't need a router, but I'm wondering if this is the right approach.
Click on the menu:
setContent(<QueryIndicators />)
I have a Content
section that displays the current component:
const Login = () => { const REACT_VERSION = React.version const [collapsed, setCollapsed] = useState(true) const [content, setContent] = useState(<QueryIndicators />) return ( <Layout className="layout"> <Sider className="layout__sider" collapsible collapsed={collapsed} onCollapse={value => setCollapsed(value)} > <Menu mode="inline" defaultSelectedKeys={['1']} className="layout__sider-menu" > <Menu.Item key="1" icon={<HomeTwoTone twoToneColor={'#184287'} />} onClick={() => setContent(<QueryIndicators />)} > Home </Menu.Item> <Menu.Item key="2" icon={<PlayCircleOutlined />} onClick={() => setContent(<QueryExecutor />)} > Executor </Menu.Item > </Menu> </Sider> <Layout> <Header className="layout__header"> {React.createElement( collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, { className: 'trigger', onClick: () => setCollapsed(!collapsed) } )} <h1 className="layout__header-text" title={'React:' + REACT_VERSION} > POA Console HOME </h1> </Header> <Content className="layout__content">{content}</Content> </Layout> </Layout> ) } export default Login
P粉6271364502023-09-12 00:56:42
How you want to apply conditional logic to display/render content based on user interaction is subjective, but you have options.
Using local state seems okay, but I will warn you, storing JSX in state, storing some data (such as a reference to a component) and mapping it is considered a React anti-pattern to declare the JSX you want to render.
Example:
const QUERY_CONTENT = { QueryExecutor, QueryIndicators, } const Login = () => { const REACT_VERSION = React.version; const [collapsed, setCollapsed] = useState(true); const [QueryContent, setQueryContent] = useState(QUERY_CONTENT.QueryIndicators); return ( <Layout className="layout"> <Sider className="layout__sider" collapsible collapsed={collapsed} onCollapse={value => setCollapsed(value)} > <Menu mode="inline" defaultSelectedKeys={['1']} className="layout__sider-menu" > <Menu.Item key="1" icon={<HomeTwoTone twoToneColor={'#184287'} />} onClick={() => setQueryContent(QUERY_CONTENT.QueryIndicators)} > Home </Menu.Item> <Menu.Item key="2" icon={<PlayCircleOutlined />} onClick={() => setQueryContent(QUERY_CONTENT.QueryExecutor)} > Executor </Menu.Item > </Menu> </Sider> <Layout> <Header className="layout__header"> {React.createElement( collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, { className: 'trigger', onClick: () => setCollapsed(collapsed => !collapsed) } )} <h1 className="layout__header-text" title={'React:' + REACT_VERSION} > POA Console HOME </h1> </Header> <Content className="layout__content"> <QueryContent /> </Content> </Layout> </Layout> ); };
If you want to use react-router
and routing to manage conditional rendering of content, then convert the component into a layout component that renders an Outlet
for the nested The route along which the component should be rendered. The router/router will manage route matching and render specific route content.
Example:
import { Outlet, useNavigate } from 'react-router-dom'; const REACT_VERSION = React.version; const AppLayout = () => { const navigate = useNavigate(); const [collapsed, setCollapsed] = useState(true); return ( <Layout className="layout"> <Sider className="layout__sider" collapsible collapsed={collapsed} onCollapse={setCollapsed} > <Menu mode="inline" defaultSelectedKeys={['1']} className="layout__sider-menu" > <Menu.Item key="1" icon={<HomeTwoTone twoToneColor={'#184287'} />} onClick={() => navigate("/queryIndicators")} > Home </Menu.Item> <Menu.Item key="2" icon={<PlayCircleOutlined />} onClick={() => navigate("/queryExecutor")} > Executor </Menu.Item > </Menu> </Sider> <Layout> <Header className="layout__header"> {React.createElement( collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, { className: 'trigger', onClick: () => setCollapsed(collapsed => !collapsed) } )} <h1 className="layout__header-text" title={'React:' + REACT_VERSION} > POA Console HOME </h1> </Header> <Content className="layout__content"> <Outlet /> // <-- nested routes render here </Content> </Layout> </Layout> ); }
import { Routes, Route } from 'react-router-dom'; const App = () => { ... return ( ... <Routes> ... <Route element={<AppLayout />}> ... <Route path="/queryIndicators" element={<QueryIndicators />} /> <Route path="/queryExecutor" element={<QueryExecutor />} /> ... </Route> ... </Routes> ... ); };
import { BrowserRouter as Router } from 'react-router-dom'; ... <Router> <App /> </Router>