如何定位要切换的特定项目使用 React Hooks 点击?



>我有一个导航栏组件,其中包含从CMS中提取的实际信息。 某些导航链接具有单击的下拉组件,而其他导航链接则没有。 我很难弄清楚如何使用 React Hooks 定位特定的菜单索引 - 目前在点击上,它会一次打开所有下拉菜单,而不是我点击的特定菜单。

prop toggleOpen 正在传递到基于 handleDropDownClick 事件处理程序的样式化组件。

这是我的组件。

const NavBar = props => {
const [links, setLinks] = useState(null);
const [notFound, setNotFound] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const fetchLinks = () => {
if (props.prismicCtx) {
// We are using the function to get a document by its uid
const data = props.prismicCtx.api.query([
Prismic.Predicates.at('document.tags', [`${config.source}`]),
Prismic.Predicates.at('document.type', 'navbar'),
]);
data.then(res => {
const navlinks = res.results[0].data.nav;
setLinks(navlinks);
});
}
return null;
};
const checkForLinks = () => {
if (props.prismicCtx) {
fetchLinks(props);
} else {
setNotFound(true);
}
};
useEffect(() => {
checkForLinks();
});
const handleDropdownClick = e => {
e.preventDefault();
setIsOpen(!isOpen);
};
if (links) {
const linkname = links.map(item => {
// Check to see if NavItem contains Dropdown Children
return item.items.length > 1 ? (
<Fragment>
<StyledNavBar.NavLink onClick={handleDropdownClick} href={item.primary.link.url}>
{item.primary.label[0].text}
</StyledNavBar.NavLink>
<Dropdown toggleOpen={isOpen}>
{item.items.map(subitem => {
return (
<StyledNavBar.NavLink href={subitem.sub_nav_link.url}>
<span>{subitem.sub_nav_link_label[0].text}</span>
</StyledNavBar.NavLink>
);
})}
</Dropdown>
</Fragment>
) : (
<StyledNavBar.NavLink href={item.primary.link.url}>
{item.primary.label[0].text}
</StyledNavBar.NavLink>
);
});
// Render
return (
<StyledNavBar>
<StyledNavBar.NavContainer wide>
<StyledNavBar.NavWrapper row center>
<Logo />
{linkname}
</StyledNavBar.NavWrapper>
</StyledNavBar.NavContainer>
</StyledNavBar>
);
}
if (notFound) {
return <NotFound />;
}
return <h2>Loading Nav</h2>;
};
export default NavBar;

你的问题是你的状态只处理一个布尔值(是否打开),但你实际上需要多个布尔值(每个菜单项一个"是否打开")。你可以尝试这样的事情:

const [isOpen, setIsOpen] = useState({});

const handleDropdownClick = e => {
e.preventDefault();
const currentID = e.currentTarget.id;
const newIsOpenState = isOpen[id] = !isOpen[id];
setIsOpen(newIsOpenState);
};

最后在你的 HTML 中:

const linkname = links.map((item, index) => {
// Check to see if NavItem contains Dropdown Children
return item.items.length > 1 ? (
<Fragment>
<StyledNavBar.NavLink id={index} onClick={handleDropdownClick} href={item.primary.link.url}>
{item.primary.label[0].text}
</StyledNavBar.NavLink>
<Dropdown toggleOpen={isOpen[index]}>
// ... rest of your component

请注意.map函数中的新索引变量,该变量用于标识您正在单击的菜单项。

更新:

我遗漏的一点是初始化,正如@MattYao在另一个答案中提到的。在负载数据中,执行以下操作:

data.then(res => {
const navlinks = res.results[0].data.nav;
setLinks(navlinks);
setIsOpen(navlinks.map((link, index) => {index: false}));
});

与您的问题无关,但您可能需要考虑跳过效果并包含您的.map密钥

我可以看到前两个 useState 钩子按预期工作。问题是你的第三个 useState() 钩子。

问题很明显,您引用的相同状态变量 isOpen 由元素列表组成,因此它们都具有相同的状态。为了解决这些问题,我建议以下方法:

  1. 您需要使用数组或 Map 初始化状态,而不是有一个值 isOpen,以便您可以引用每个单独的值:

    const initialOpenState = [] // or using ES6 Map - new Map([]);
    
  2. 在 fetchLink 函数回调中,将 isOpen 状态数组值初始化为 false。所以你可以把它放在这里:

    data.then(res => {
    const navlinks = res.results[0].data.nav;
    setLinks(navlinks);
    // init your isOpen state here
    navlinks.forEach(link => isOpen.push({ linkId: link.id, value: false })) //I suppose you can get an id or similar identifers
    });
    
  3. 在handleClick函数中,您必须定位链接对象并将其设置为true,而不是将所有内容设置为true。您可能需要使用 .find() 来查找您正在单击的链接:

    handleClick = e => {
    const currentOpenState = state;
    const clickedLink = e.target.value // use your own identifier
    currentOpenState[clickedLink].value = !currentOpenState[clickedLink].value;
    setIsOpen(currentOpenState);
    }
    
  4. 更新组件,以便使用正确的 isOpen 状态:

    <Dropdown toggleOpen={isOpen[item].value}> // replace this value
    {item.items.map(subitem => {
    return (
    <StyledNavBar.NavLink href={subitem.sub_nav_link.url}>
    <span>{subitem.sub_nav_link_label[0].text}</span>
    </StyledNavBar.NavLink>
    );
    })}
    </Dropdown>
    

如果您只是复制和粘贴,上面的代码可能不适合您。但它应该让你了解事情应该如何协同工作。

相关内容

  • 没有找到相关文章

最新更新