如何将 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
问题
NavItems
和 Dropdown
组件在语法上是正确的,但是您在每个组件中将 props
对象命名为其他名称,分别为 items
和 submenus
.然后每个组件引用 entire“道具”对象,就好像它是 specific items
或 submenus
道具一样通过。
解决方案
将每个重命名为 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>
);
}
我正在尝试将列表 (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
问题
NavItems
和 Dropdown
组件在语法上是正确的,但是您在每个组件中将 props
对象命名为其他名称,分别为 items
和 submenus
.然后每个组件引用 entire“道具”对象,就好像它是 specific items
或 submenus
道具一样通过。
解决方案
将每个重命名为 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>
);
}