ОБНОВЛЕНИЕ: После некоторых экспериментов я решил, что проблема в том, что у меня есть некоторый код (см. Раздел useEffect()
ниже), который обновляет аккордеон при изменении объекта menu
. На. первый рендер defaultActiveKey
работает, но при последующих повторных рендерингах он не работает.
Я использую элемент управления Accordion из реагировать - bootstrap и могу получить базовые данные c пример из документации, работающей, но после небольшой настройки кода, аккордеон по умолчанию больше не открывается ... по умолчанию. Вот, пожалуй, самая интересная часть кода:
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;