首页 > 解决方案 > Next.js 基于选中项渲染组件

问题描述

我正在使用 Next.js 创建一个 Web 应用程序,其中用户一旦登录,就会有一个带有不同选项(内容)的侧边栏,我有一个页面/dashboard/[id].js,用户一旦登录就会被推送。

接下来,我有一个表示不同组件的数组以及与它们相关的一些选项:

const contents = [
  { name: "spreadsheet", component: <Spreadsheet /> },
  { name: "streamlit", component: <StreamlitEmbed /> },
];

这些内容正在侧边栏中呈现,我希望默认情况下呈现第一个元素:

{contents.map((content) => {
                  console.log(content);
                  return (
                    <SidebarElement
                      text={content.name}
                      router={router}
                      iconName={`/${content.name}.svg`}
                      isSelected={
                        contents.findIndex((c) => c === content) === 0
                      }
                    />
                  );
                })}

我希望仪表板能够呈现用户从侧边栏中选择的组件,我不确定 Next.js 中的内置路由器是否能够执行类似的操作。由于我正在寻找一种更类似于 r react-router的方法

我曾考虑将内容的名称附加到 URL,以便在加载时我将有一个带有第一个内容名称的 URL,并且当用户单击另一个内容时,该 URL 正在更改并且用户重定向,但它似乎他们认为,采用这种方法需要有n页面,每个内容都有一个页面,理想情况下,应该动态生成。

仅供参考,我附上整个Dashboard.js

import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import Image from "next/image";
import Link from "next/link";

import StreamlitEmbed from "../../components/StreamlitEmbed";
import Header from "../../components/Header";
import Spinner from "../../components/Spinner/Spinner";
import SidebarElement from "../../components/SidebarElement";
import Spreadsheet from "../../components/Spreadsheet/Spreadsheet";

const contents = [
  { name: "spreadsheet", component: <Spreadsheet /> },
  { name: "streamlit", component: <StreamlitEmbed /> },
];

import { Auth } from "aws-amplify";

function Dashboard() {
  const router = useRouter();

  const [user, setUser] = useState(null);
  const [sidebarOpen, setSidebarOpen] = useState(false);

  const displayName = user?.attributes["custom:displayName"];
  const groups =
    user?.signInUserSession.accessToken.payload["cognito:groups"] || [];

  useEffect(() => {
    const getUser = async () => {
      Auth.currentAuthenticatedUser()
        .then((user) => {
          setUser(user);
        })
        .catch((err) => {
          console.log(err);
          setUser(null);
          router.push("/login");
        });
    };
    getUser();
  }, []);

  return (
    <>
      {user ? (
        <div>
          <div className="flex h-screen">
            <div
              onClick={() => setSidebarOpen(false)}
              className={`${
                sidebarOpen ? "block" : "hidden"
              } fixed z-20 inset-0 bg-primaryColor opacity-50 transition-opacity lg:hidden`}
            />
            <div
              className={`${
                sidebarOpen
                  ? "translate-x-0 ease-out"
                  : "-translate-x-full ease-in"
              } fixed z-30 inset-y-0 left-0 w-64 transition duration-300 transform bg-primaryColor overflow-y-auto lg:translate-x-0 lg:static lg:inset-0 bg-main`}
            >
              <div className="flex items-center justify-center mt-8">
                <div className="flex items-center">
                  <Image src={"/logo.svg"} height={85} width={100} />
                </div>
              </div>
              <nav className="mt-10">
                {contents.map((content) => {
                  console.log(content);
                  return (
                    <SidebarElement
                      text={content.name}
                      router={router}
                      iconName={`/${content.name}.svg`}
                      isSelected={
                        contents.findIndex((c) => c === content) === 0
                          ? true
                          : false
                      }
                    />
                  );
                })}
              </nav>
              <div className="p-2 absolute bottom-0 left-2 text-gray-200">
                <p>V 2.0</p>
              </div>
            </div>
            <div className="flex-1 flex flex-col overflow-hidden">
              <Header
                setSidebarOpen={setSidebarOpen}
                displayName={displayName}
                groups={groups}
              />

              <Spreadsheet />
            </div>
          </div>
        </div>
      ) : (
        <Spinner />
      )}
    </>
  );
}

export default Dashboard;

标签: reactjsnext.js

解决方案


推荐阅读