使用Grid与styled-components无法正确渲染React五分屏组件
问题描述
我之前已经学会在父容器使用display: flex、子元素使用flex: 1实现二分屏组件。现在尝试通过display: grid构建一个五分屏组件:左侧侧边栏占据第一列及两行空间,其余四个组件分别占据一列一行。目前已能渲染出网格结构,但仅第一行第一列能显示内容,其余区域无文本展示。我使用了React Router与styled-components,相关代码及截图如下:

相关代码
App.js
import React from "react"; import { Routes, Route } from "react-router-dom"; import styled, { createGlobalStyle } from "styled-components"; import {NoMatch} from "./pages/NoMatch"; import {Dashboard} from "./pages/Dashboard"; import {About} from "./pages/About"; import {Home} from "./pages/Home"; import { LayoutNavigation } from "./components/LayoutNavigation"; export default function App() { return ( <> <Routes> <Route path="/" element={<LayoutNavigation />}> <Route index element={<Home />} /> <Route path="about" element={<About />} /> <Route path="dashboard" element={<Dashboard />} /> <Route path="*" element={<NoMatch />} /> </Route> </Routes> </> ); }
Home.js
import { SplitScreenQuad } from "../components/SplitScreen"; import styled from "styled-components"; const Sidebar = () => { return ( <div> <h1 style={{ backgroundColor: "lightblue" }}>Sidebar</h1> </div> ); }; const UserInputFields = () => { <div> <h1 style={{ backgroundColor: "lightgreen" }}>UserInputFields</h1>; </div>; }; const UserData = () => { <div> <h1 style={{ backgroundColor: "lightgreen" }}>UserData</h1>; </div>; }; const TableResults = () => { <div> <h1 style={{ backgroundColor: "pink" }}>TableResults</h1>; </div>; }; const ImageResults = () => { <div> <h1 style={{ backgroundColor: "yellow" }}>ImageResults</h1>; </div>; }; export const Home = () => { return ( <> <h1>HOME</h1> <SplitScreenQuad sidebar={Sidebar} topleft={UserInputFields} topright={UserData} bottomleft={TableResults} bottomright={ImageResults} /> </> ); };
SplitScreen.js
/*Filename: SplitScreen.js*/ import React from "react"; import styled from "styled-components"; export const SplitScreenQuad = ({ sidebar: Sidebar, topleft: Topleft, topright: Topright, bottomleft: Bottomleft, bottomright: Bottomright, }) => { return ( <> <ContainerQuad> <PaneQuad> <Sidebar id="sidebar" /> </PaneQuad> <PaneQuad> <Topleft id="topleft" /> </PaneQuad> <PaneQuad> <Topright id="topright" /> </PaneQuad> <PaneQuad> <Bottomleft id="bottomleft" /> </PaneQuad> <PaneQuad> <Bottomright id="bottomright" /> </PaneQuad> </ContainerQuad> </> ); }; const ContainerQuad = styled.div` display: grid; grid-template-columns: auto 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 1rem; background-color: lightcoral; #sidebar { grid-column: 1; grid-row: 1 / span 2; } #topleft { grid-column: 2; grid-row: 1; } #topright { grid-column: 3; grid-row: 1; } #bottomleft { grid-column: 2; grid-row: 2; } #bottomright { grid-column: 3; grid-row: 2; } `; const PaneQuad = styled.div``;
解决方案
问题出在Home.js里的四个子组件没有正确返回JSX内容:
UserInputFields、UserData、TableResults、ImageResults这几个箭头函数组件,你写了JSX但没有用return语句返回,也没有用括号直接包裹JSX(箭头函数隐式返回的语法要求)。
修改后的Home.js相关组件代码如下:
const UserInputFields = () => { return ( <div> <h1 style={{ backgroundColor: "lightgreen" }}>UserInputFields</h1> </div> ); }; const UserData = () => ( <div> <h1 style={{ backgroundColor: "lightgreen" }}>UserData</h1> </div> ); const TableResults = () => ( <div> <h1 style={{ backgroundColor: "pink" }}>TableResults</h1> </div> ); const ImageResults = () => ( <div> <h1 style={{ backgroundColor: "yellow" }}>ImageResults</h1> </div> );
两种写法都可以:要么显式写return加括号,要么直接用括号包裹JSX实现箭头函数的隐式返回。
另外可以优化一下SplitScreen的网格布局写法,避免使用ID选择器,改用给PaneQuad传递props来控制网格位置,让代码更符合React组件化的思路:
// 修改SplitScreen.js export const SplitScreenQuad = ({ sidebar: Sidebar, topleft: Topleft, topright: Topright, bottomleft: Bottomleft, bottomright: Bottomright, }) => { return ( <ContainerQuad> <PaneQuad area="sidebar"> <Sidebar /> </PaneQuad> <PaneQuad area="topleft"> <Topleft /> </PaneQuad> <PaneQuad area="topright"> <Topright /> </PaneQuad> <PaneQuad area="bottomleft"> <Bottomleft /> </PaneQuad> <PaneQuad area="bottomright"> <Bottomright /> </PaneQuad> </ContainerQuad> ); }; const ContainerQuad = styled.div` display: grid; grid-template-columns: auto 1fr 1fr; grid-template-rows: 1fr 1fr; grid-template-areas: "sidebar topleft topright" "sidebar bottomleft bottomright"; gap: 1rem; background-color: lightcoral; `; const PaneQuad = styled.div` grid-area: ${props => props.area}; `;
这种用grid-template-areas的写法可读性更强,也不需要依赖ID来定位网格项。
内容的提问来源于stack exchange,提问作者ahauser
相关产品推荐
相关产品推荐

