我在 NextJS 应用程序中有一个侧边栏,并且有一个主要组件放置在一行中。侧边栏有多个项目,单击每个项目会通过推送路线(更新 url)来更新主要内容
<Preview/>
,但这会重新渲染侧边栏和主要内容。我的理解是组件放置不正确导致了问题。现在我已将侧边栏和主要组件放置在 <Home/>
内
文件夹结构和组件结构应该如何?考虑到 Main 组件是一个动态组件(根据传递给它的 id 进行渲染)。
这是文件夹结构
project-root /
├──src
│ ├── app /
│ │ ├── models /
│ │ │ ├── Log.ts
│ │ ├── services /
│ │ │ ├── LogService.ts
│ │ ├── components /
│ │ │ ├── Sidebar.tsx
│ │ │ ├── Navbar.tsx
│ │ │ ├── Preview.tsx
│ │ │ └── Home.tsx
│ │ │ │
│ │ ├── logs /
│ │ │ ├──[id]
│ │ │ │ ├── page.tsx
│ │ └── layout.tsx
│ │ └── global.css
│ │ └── page.tsx
这是动态页面
logs/[id]/page.tsx
// logs/[id]/page.tsx
import Home from '@/app/_components/Home';
import LogService from '../../_services/logService';
// This is required for dynamic routing in runtime
export const dynamicParams = true;
export async function generateStaticParams() {
const logService = new LogService();
const logs = await logService.fetchLogs();
return logs.map(log => ({ id: log.id }));
}
export default function Page({ params }: { params: { id: string } }) {
const { id } = params;
return <Home id={id} />
};
// _components/Home.tsx
"use client";
import IconButton from "./IconButton";
import PSNavbar from "./PSNavbar";
import Pastelog from "./Pastelog";
import Preview from './Preview';
import Sidebar from './Sidebar';
import { Theme } from './ThemeSwitcher';
export default function Home({ id }: { id: string | null }) {
const [showSideBar, setShowSideBar] = useState<boolean>(true);
const [logs, setLogs] = useState<Log[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [selectedLogId, setSelectedLogId] = useState<string | null>(id);
...
return (
<div className={`flex h-screen ${theme == Theme.DARK ? 'darkTheme' : 'lightTheme'}`}>
{
(showSideBar && <IconButton
onClick={() => setShowSideBar(!showSideBar)}>
<ViewSidebarRoundedIcon />
</IconButton>
)
}
<div>
{showSideBar && (
<Sidebar
loading={loading}
logs={logs}
id={selectedLogId}
onLogClick={(id) => {
if (id) {
router.push('/logs/$id');
setSelectedLogId(id!);
} else {
setSelectedLogId(null);
router.push('/');
}
}}
/>
)}
</div>
{/* Main content */}
<div className={`grow overflow-y-auto transition-all duration-800 ${showSideBar ? 'pl-64' : 'pl-0'}`}>
<div className="flex flex-col h-full">
<PSNavbar
sideBarIcon={!showSideBar}
onToggleSidebar={() => setShowSideBar(!showSideBar)}
/>
{
selectedLogId ? (<Preview
id={selectedLogId}
showNavbar={false}
/>) :
(<Pastelog />)
}
</div>
</div>
</div>
);
}
这种方法的问题是我想在侧边栏中选择列表项时更新 url 它可以工作,但这会触发整个主页的重新渲染(预期),但我希望只渲染主要内容.
此外,如果用户通过链接访问网站
<baseurl>/sidebar-item
,我希望应用程序能够加载选定的侧边栏项目(目前工作正常)
完整源代码在这里
这是上述代码的输出,显示侧边栏重新渲染
如果侧边栏内容对于所有页面都是通用的,那么您可以将侧边栏组件移动到布局文件中。 例如:
export default function Layout ({ children } : { children : React.ReactNode}) {
return <>
<Sidebar />
{children} //page content will go here
</>
}
您正在使用路由器,它用于重新渲染整个应用程序并重定向到所需的页面。我建议使用组件来简单地切换组件。