react引导程序手风琴defaultActiveKey未打开默认活动密钥



UPDATE:经过一些实验,我确定问题在于我有一些代码(请参阅下面的useEffect()部分(,当menu对象更改时,它会更新手风琴。在第一次渲染时,defaultActiveKey可以工作,但在随后的重新渲染时,它不能工作。

我使用的是react bootstrap中的Accordion控件,可以从正在工作的文档中获得基本示例,但在对代码进行了大量自定义后,默认Accordio将不再默认打开。这可能是代码中最有趣的部分:

return (
<>
<MenuMobile menuItems={menuItems} open={open} setOpen={setOpen} />
<Navbar bg="white" variant="light" expand="lg" fixed="left">
<Navbar.Brand href="/home">
<img src={logo} width="113" height="40" alt={siteTitle + " Logo"} />
</Navbar.Brand>
<NavbarToggler open={open} setOpen={setOpen} />
<Accordion
defaultActiveKey={menu.defaultActiveKey}
className="sidebar-menu"
data-active={menu.defaultActiveKey}
>
{menu.cards.map((card, index) => {
return (
<Card key={index}>
<CustomToggle title={card.title} eventKey={card.eventKey} anchors={card.anchors} />
<Accordion.Collapse eventKey={card.eventKey}>
<Card.Body>
{card.anchors.map((anchor) => (
<a href={`#${anchor.href}`} key={anchor.href}>
{anchor.text}
</a>
))}
</Card.Body>
</Accordion.Collapse>
</Card>
);
})}
</Accordion>
</Navbar>
</>
);

我在数据属性中输出了menu.defaultActiveKey,只是为了确保它正确无误。我怀疑问题与我动态生成子<Card>组件有关,但我不确定修复方法是什么?

如果你感兴趣,整个源代码如下:

import React, { useState, useContext, useEffect } from "react";
import PropTypes from "prop-types";
import Navbar from "react-bootstrap/Navbar";
import AccordionContext from "react-bootstrap/AccordionContext";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import { useAccordionToggle } from "react-bootstrap/AccordionToggle";
import classNames from "classnames";
import queryString from "query-string";
import MenuMobile from "./menuMobile";
import NavbarToggler from "./navbarToggler";
import EduMenus from "../utility/educationMenus";
import logo from "../images/logo-white.svg";
const CustomToggle = ({ title, eventKey, anchors, callback }) => {
const currentEventKey = useContext(AccordionContext);
const onClickToggle = useAccordionToggle(eventKey, () => {
callback(eventKey);
});
const isOpen = currentEventKey === eventKey;
return (
<div className={classNames("card-header", { open: isOpen })} onClick={onClickToggle}>
<h2>{title}</h2>
{!!anchors.length && <i className={classNames("fa", { "fa-angle-down": !isOpen }, { "fa-angle-up": isOpen })} />}
</div>
);
};
CustomToggle.propTypes = {
title: PropTypes.string.isRequired,
eventKey: PropTypes.string.isRequired,
anchors: PropTypes.array,
callback: PropTypes.func,
};
CustomToggle.defaultProps = {
anchors: [],
callback: () => null,
};
const DocsNavbar = ({ siteTitle, location }) => {
const [open, setOpen] = useState(false);
const [menu, setMenu] = useState(EduMenus.default);
const menuItems = [
{
href: "/education/overview",
text: "Education",
},
{
href: "/home",
text: "Business",
},
{
href: "/home",
text: "Travel",
},
{
href: "/home",
text: "Healthcare",
},
];
useEffect(() => {
if (!!location && location.search !== "") {
const params = queryString.parse(location.search);
if (params.menu) {
if (Object.prototype.hasOwnProperty.call(EduMenus, params.menu)) {
setMenu(EduMenus[params.menu]);
} else {
console.error(`Menu named '${params.menu}' does not exist`);
}
}
}
});
return (
<>
<MenuMobile menuItems={menuItems} open={open} setOpen={setOpen} />
<Navbar bg="white" variant="light" expand="lg" fixed="left">
<Navbar.Brand href="/home">
<img src={logo} width="113" height="40" alt={siteTitle + " Logo"} />
</Navbar.Brand>
<NavbarToggler open={open} setOpen={setOpen} />
<Accordion
defaultActiveKey={menu.defaultActiveKey}
className="sidebar-menu"
data-active={menu.defaultActiveKey}
>
{menu.cards.map((card, index) => {
return (
<Card key={index}>
<CustomToggle title={card.title} eventKey={card.eventKey} anchors={card.anchors} />
<Accordion.Collapse eventKey={card.eventKey}>
<Card.Body>
{card.anchors.map((anchor) => (
<a href={`#${anchor.href}`} key={anchor.href}>
{anchor.text}
</a>
))}
</Card.Body>
</Accordion.Collapse>
</Card>
);
})}
</Accordion>
</Navbar>
</>
);
};
DocsNavbar.propTypes = {
siteTitle: PropTypes.string,
location: PropTypes.object,
};
DocsNavbar.defaultProps = {
siteTitle: ``,
};
export default DocsNavbar;

好的,所以我想出了一个解决办法。不确定这是否是最好的方法,但它有效,所以我会把它放在那里,但如果有人有更好的解决方案,我会洗耳恭听。

基本上,我删除了defaultActiveKey,因为它似乎只适用于初始渲染,并用activeKey显式地设置活动手风琴,并将其保持在状态,并在菜单更改时设置该状态。

import React, { useState, useContext, useEffect } from "react";
import PropTypes from "prop-types";
import Navbar from "react-bootstrap/Navbar";
import AccordionContext from "react-bootstrap/AccordionContext";
import Accordion from "react-bootstrap/Accordion";
import Card from "react-bootstrap/Card";
import { useAccordionToggle } from "react-bootstrap/AccordionToggle";
import classNames from "classnames";
import queryString from "query-string";
import MenuMobile from "./menuMobile";
import NavbarToggler from "./navbarToggler";
import EduMenus from "../utility/educationMenus";
import logo from "../images/logo-white.svg";
const CustomToggle = ({ title, eventKey, anchors, callback }) => {
const currentEventKey = useContext(AccordionContext);
const onClickToggle = useAccordionToggle(eventKey, () => {
callback(eventKey);
});
const isOpen = currentEventKey === eventKey;
return (
<div className={classNames("card-header", { open: isOpen })} onClick={onClickToggle}>
<h2>{title}</h2>
{!!anchors.length && <i className={classNames("fa", { "fa-angle-down": !isOpen }, { "fa-angle-up": isOpen })} />}
</div>
);
};
CustomToggle.propTypes = {
title: PropTypes.string.isRequired,
eventKey: PropTypes.string.isRequired,
anchors: PropTypes.array,
callback: PropTypes.func,
};
CustomToggle.defaultProps = {
anchors: [],
callback: () => null,
};
const DocsNavbar = ({ siteTitle, location }) => {
const [open, setOpen] = useState(false);
const [menu, setMenu] = useState(EduMenus.default);
const [active, setActive] = useState(EduMenus.default.defaultActiveKey);
const menuItems = [
{
href: "/education/overview",
text: "Education",
},
{
href: "/home",
text: "Business",
},
{
href: "/home",
text: "Travel",
},
{
href: "/home",
text: "Healthcare",
},
];
useEffect(() => {
if (!!location && location.search !== "") {
const params = queryString.parse(location.search);
if (params.menu) {
if (Object.prototype.hasOwnProperty.call(EduMenus, params.menu)) {
setMenu(EduMenus[params.menu]);
setActive(EduMenus[params.menu].defaultActiveKey);
} else {
console.error(`Menu named '${params.menu}' does not exist`);
}
}
}
});
return (
<>
<MenuMobile menuItems={menuItems} open={open} setOpen={setOpen} />
<Navbar bg="white" variant="light" expand="lg" fixed="left">
<Navbar.Brand href="/home">
<img src={logo} width="113" height="40" alt={siteTitle + " Logo"} />
</Navbar.Brand>
<NavbarToggler open={open} setOpen={setOpen} />
<Accordion activeKey={active} className="sidebar-menu" onSelect={(e) => setActive(e)}>
{menu.cards.map((card, index) => {
return (
<Card key={index}>
<CustomToggle title={card.title} eventKey={card.eventKey} anchors={card.anchors} />
<Accordion.Collapse eventKey={card.eventKey}>
<Card.Body>
{card.anchors.map((anchor) => (
<a href={`#${anchor.href}`} key={anchor.href}>
{anchor.text}
</a>
))}
</Card.Body>
</Accordion.Collapse>
</Card>
);
})}
</Accordion>
</Navbar>
</>
);
};
DocsNavbar.propTypes = {
siteTitle: PropTypes.string,
location: PropTypes.object,
};
DocsNavbar.defaultProps = {
siteTitle: ``,
};
export default DocsNavbar;

最新更新