React嵌套路由中CSS类样式不生效的解决方法咨询
我创建了用于基础样式的CSS文件,其中.mainContent和.content类在普通路由(如/films、/planets)中正常生效,但在/people及/people/:id这类嵌套路由中无法生效。希望让这两个嵌套路由也能应用.content类的flex布局样式,以下是我的代码:
Main.js 代码
import {Routes,Route, useLocation} from 'react-router-dom' //import {Redirect} from 'react' import { Films } from '../Films/Films' import { People } from '../People/People' //import { Planet } from '../Planet/Planet' import { Planets } from '../Planets/Planets' import {useState,useEffect} from 'react' import { Person } from '../Person/Person' import { Home } from '../Home/Home' export const Main = (props) => { const { pathname } = useLocation(); const [people, setPeople] = useState([]); useEffect(() => { (async function () { if (pathname.indexOf('/people') > -1) { let resp = await fetch('https://swapi.dev/api/people'); let data = await resp.json(); console.log('Fetched the people. Updating people state'); setPeople(data.results); } })(); }, [pathname]); return ( <div className='mainContent content'> <Routes> <Route path="/films/*" element={<Films/>}></Route> <Route path="/planets/*" element={<Planets/>}></Route> <Route path="/people" element={<People list={people} />}> <Route path="/people/:id" element={<Person list={people} />}/> {/* Person is passed prop with fetch results */} </Route> <Route path="*" element={<Home />}> </Route> </Routes> </div> ) }
CSS 文件代码
.mainContent { width: 100%; display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start; } .mainContent > div { /* one column for list, one for details */ flex-basis: 50%; flex-grow: 0; flex-shrink: 1; width: 50%; padding: 1rem; min-height: 40vh; } .content{ display:flex; flex-direction: row; }
解决方法
1. 修正嵌套路由的路径写法
把子路由的绝对路径改为相对路径,父路由已经指定/people,子路由只需写:id即可:
<Route path="/people" element={<People list={people} />}> <Route path=":id" element={<Person list={people} />}/> </Route>
2. 在People组件中添加<Outlet/>
React Router的嵌套路由需要通过<Outlet/>来渲染子路由内容,所以要在People组件的JSX中加入这个组件,确保Person能渲染到People内部:
// People.js 示例代码 import { Outlet } from 'react-router-dom'; export const People = ({ list }) => { return ( <div> {/* 这里放People组件的列表内容 */} <Outlet /> {/* 子路由Person会渲染在这里 */} </div> ); };
3. 确认组件结构与样式继承
你的CSS中.mainContent > div是针对.mainContent的直接子元素设置样式,修正路由后,People组件的根元素会成为.mainContent的直接子元素,而Person通过Outlet渲染在People内部,此时需要确保People的根元素不会破坏flex布局——比如不要设置display: block,或者可以给People的根元素也添加flex相关属性,让它和其他路由组件保持一致的布局。
原因说明
之前的子路由用了绝对路径/people/:id,这会让Person组件直接渲染在<Routes>下,而不是People组件内部,导致Person的DOM结构脱离了.mainContent的直接子元素范围,.mainContent > div的样式就无法作用到它。修正路径并添加Outlet后,整个/people相关的内容都嵌套在.mainContent的容器结构中,flex布局样式就能正常生效了。
内容的提问来源于stack exchange,提问作者Iram Kahkashan

