react-bootstrap手风琴defaultActiveKey未打开默认活动键

问题描述 投票:0回答:1

更新:经过一些试验,我确定问题是我有一些代码(请参阅下面的useEffect()部分),该代码在menu对象更改时会更新手风琴。上。在第一个渲染中,defaultActiveKey有效,但在随后的重新渲染中却无效。

我正在使用react-bootstrap中的Accordion控件,并且可以从文档中获取基本示例,但是在对代码进行了很多自定义之后,默认情况下默认手风琴不再打开...默认情况下。这可能是代码中最有趣的部分:

  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;
reactjs react-bootstrap
1个回答
0
投票
[基本上,我删除了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;

© www.soinside.com 2019 - 2024. All rights reserved.