如何将 jsx 反应组件(带道具)正确传递到带有下拉列表的导航栏组件中?

How can I pass a jsx react component (with prop) into a Navbar component with a Dropdown properly?

我正在尝试将列表 (NavItemsList) 传递到我的导航栏中,以便它使用列表项及其各自的子导航和下拉组件填充“right-nav-container”div。我是 React.Js 的新手,如果我错了请纠正我;在容器的右侧,我正在读取具有特定索引的列表并映射其值。我设置了我的代码,这样一旦它映射了值,它就会 return 我的“NavItems”组件和我创建的“items”道具。在 NavItems 组件内,我有一个条件语句,用于检查读取的列表在索引中是否有子导航部分。如果它有一个子导航,那么我制作的 Dropdown 组件将被传递,它还有另一个名为 submenus 的道具,否则只有索引标题被传递到导航栏中。在下拉组件内部,我将“子菜单”作为道具(我认为)传递给它,用于获取下拉菜单的 subNav 值。我的问题是,当我在 Navbar 文件中传递 NavItems 组件时,我的整个 Navbar 都消失了,但是当我注释掉 return <NavItems items={menu} key={index} />; 时,我的 Navbar 加载正常(右容器中没有链接)。这让我相信我在以下组件之一中做错了。

Navbar.jsx 部分:

import React, {useState} from 'react';
import {Link} from 'react-router-dom'; 
import './Navbar.css';
import Dropdown from './Dropdown';
import {NavItemsList} from './NavItemsList';
import NavItems from './NavItems';

function Navbar() {
    const [click, setClick] = useState(false); 
    const [button, setButton] = useState(true);
    const [dropdown, setDropdown] = useState(false);

    const handleClick = () => setClick(!click); //Since the state is initially false (set above), clicking it will set the state to the opposite because of the ! sign.
    const closeMobileMenu = () => setClick(false);

    const onMouseEnter = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(true);
        }
    };

    const onMouseLeave = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(false);
        }
    };

    return (
<div className='right-nav-container'>
                        <ul className={click ? 'nav-menu active' : 'nav-menu'}>
                            <div className='text-links'>
                                {NavItemsList.slice(0, 4).map((menu, index) => {
                                    return <NavItems items={menu} key={index} />;
                                })}
                            </div>
                            <div className='logo-links'>
                                {NavItemsList.slice(4, 6).map((menu, index) => {
                                    return <NavItems items={menu} key={index} />;
                                })}
                            </div>
                );
}

export default Navbar;

NavItems.jsx:

import React, {useState} from 'react';
import Dropdown from './Dropdown';
import {Link} from 'react-router-dom';

function NavItems(items) {
    const [click, setClick] = useState(false);
    const handleClick = () => setClick(!click);

    return (
        <li className='nav-item'>
            {items.subNav ? (
                <>
                    <Link
                        className={items.cName}
                        to={items.path}
                        onClick={() => setClick(false)}
                    >
                        {items.title}
                    </Link>
                    <Dropdown submenus={items.subNav} />
                </>
            ) : (
                <Link
                    className={items.cName}
                    to={items.path}
                    onClick={() => setClick(false)}
                >
                    {items.title}
                </Link>
            )}
        </li>
    );
}

export default NavItems;

Dropdown.jsx:

import React, {useState} from 'react';
import {Link} from 'react-router-dom';
function Dropdown(submenus) {
    const [click, setClick] = useState(false);
    const handleClick = () => setClick(!click);

    return (
        <ul
            onClick={handleClick}
            className={click ? 'dropdown-menu clicked' : 'dropdown-menu'}
        >
            {submenus.map((subNav, index) => (
                <li key={index} className='dropdown-links'>
                    <Link
                        className={subNav.cName}
                        to={subNav.path}
                        onClick={() => setClick(false)}
                    >
                        {subNav.title}
                    </Link>
                </li>
            ))}
        </ul>
    );
}

export default Dropdown;

NavItemsList.js object 示例:

{
        title: 'Create',
        path: '/create',
        cName: 'nav-links',
        subNav: [
            {
                title: 'Pixel Art',
                path: '/create/pixelart',
                cName: 'dropdown-link',
            },
            {
                title: 'Upload',
                path: '/create/upload',
                cName: 'dropdown-link',
            },
        ],
    },

非常感谢任何帮助。我一直在尝试解决这个问题,但在加载 React 应用程序时总是出现空白屏幕。

这是一个有问题的代码沙箱:https://codesandbox.io/s/staging-sound-ljc073?file=/src/NavItemsList.js

问题

NavItemsDropdown 组件在语法上是正确的,但是您在每个组件中将 props 对象命名为其他名称,分别为 itemssubmenus .然后每个组件引用 entire“道具”对象,就好像它是 specific itemssubmenus 道具一样通过。

解决方案

将每个重命名为 props 并相应地访问:

function NavItems(props) {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick(!click);

  return (
    <li className="nav-item">
      <Link
        className={props.items.cName}
        to={props.items.path}
        onClick={() => setClick(false)}
      >
        {props.items.title}
      </Link>
      {props.items.subNav && <Dropdown submenus={props.items.subNav} />}
    </li>
  );
}

...

function Dropdown(props) {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick(!click);

  return (
    <ul
      onClick={handleClick}
      className={click ? "dropdown-menu clicked" : "dropdown-menu"}
    >
      {props.submenus.map((subNav, index) => (
        <li key={index} className="dropdown-links">
          <Link
            className={subNav.cName}
            to={subNav.path}
            onClick={() => setClick(false)}
          >
            {subNav.title}
          </Link>
        </li>
      ))}
    </ul>
  );
}

或者解构传入的props:

function NavItems({ items }) {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick(!click);

  return (
    <li className="nav-item">
      <Link
        className={items.cName}
        to={items.path}
        onClick={() => setClick(false)}
      >
        {items.title}
      </Link>
      {items.subNav && <Dropdown submenus={items.subNav} />}
    </li>
  );
}

...

function Dropdown({ submenus }) {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick(!click);

  return (
    <ul
      onClick={handleClick}
      className={click ? "dropdown-menu clicked" : "dropdown-menu"}
    >
      {submenus.map((subNav, index) => (
        <li key={index} className="dropdown-links">
          <Link
            className={subNav.cName}
            to={subNav.path}
            onClick={() => setClick(false)}
          >
            {subNav.title}
          </Link>
        </li>
      ))}
    </ul>
  );
}