使用 Reactstrap:如何一次只切换一个 Collapse?

Using Reactstrap: How to toggle only one Collapse at a time?

我正在使用 Reactstrap 打开和折叠多张卡片。一旦打开,它们就会保持打开状态,并且由于我打算使用更多它们(用于文章),所以这将是一团糟。一旦我点击一个按钮并打开一张卡片,我希望其他人关闭,所以一次只显示一张卡片。我怎样才能做到这一点?

    const [isOpenInfo, setIsOpenInfo] = useState(false);
    const toggleInfo = () => setIsOpenInfo(!isOpenInfo);

    const [isOpenArticle1, setIsOpenArticle1] = useState(false);
    const toggleArticle1 = () => setIsOpenArticle1(!isOpenArticle1);

    const [isOpenArticle2, setIsOpenArticle2] = useState(false);
    const toggleArticle2 = () => setIsOpenArticle2(!isOpenArticle2);

在我的菜单中,我有一个“更多信息”按钮,单击时,它会打开一个折叠文章列表,当单击每个标题时,它会打开该文章(但我只想让一篇文章以时间)。所以这就像崩溃中的崩溃......

<Button className="info-button" color="primary" onClick={toggleInfo}>
  More Info
</Button>

<Collapse isOpen={isOpenInfo}>
    <Card className="card">
        <CardBody className="card-body">

            <div className="section section-articles">
                <div className="articles-buttons">
                    <Button
                        className="article2-button"
                        color="primary"
                        onClick={toggleArticle2}
                    >
                      <h3>Article 2</h3>
                    </Button>
                    <Button
                        className="article1-button"
                        color="primary"
                        onClick={toggleArticle1}
                    >
                    <h3>Article 1</h3>
                    </Button>
               </div>

<Collapse isOpen={isOpenArticle2}>
    <Card className="card">
        <CardBody className="card-body">
            <Article2 />
        </CardBody>
    </Card>
</Collapse>
<Collapse isOpen={isOpenArticle1}>
    <Card className="card">
        <CardBody className="card-body">
            <Article1 />
        </CardBody>
    </Card>
</Collapse>


           </div>
        </CardBody>
    </Card>
</Collapse>

您可以创建一个包含所有文章的默认变量,并使用它来设置状态。为所有可折叠对象创建一个状态变量。

const DEFAULT_ARTICLES = {
    article1: false,
    article2: false,
};

const [articles, setArticles] = useState(DEFAULT_ARTICLES);
const toggleArticle = (key) => setArticles({
    ...DEFAULT_ARTICLES,
    [key]: true,
});

并在您的渲染函数中使用 键打开折叠并切换折叠。

<Collapse isOpen={isOpenInfo}>
                <Card className="card">
                    <CardBody className="card-body">
                        <div className="section section-articles">
                            <div class="articles-buttons">
                                <Button
                                    className="article2-button"
                                    color="primary"
                                    onClick={() => toggleArticle('article2')}
                                >
                                    <h3>Article 2</h3>
                                </Button>
                                <Button
                                    className="article1-button"
                                    color="primary"
                                    onClick={() => toggleArticle('article1')}
                                >
                                    <h3>Article 1</h3>
                                </Button>
                            </div>
                            <Collapse isOpen={articles['article1']}>
                                <Card className="card">
                                    <CardBody className="card-body">
                                        <Article2 />
                                    </CardBody>
                                </Card>
                            </Collapse>
                            <Collapse isOpen={articles['article2']}>
                                <Card className="card">
                                    <CardBody className="card-body">
                                        <Article1 />
                                    </CardBody>
                                </Card>
                            </Collapse>
                        </div>
                    </CardBody>
                </Card>
            </Collapse>

你可以用一个状态来控制所有的崩溃。

const [openedCollapse, setOpenedCollapse] = useState("");

const openCollapse = e => { // this is the button onClick handler
  setOpenedCollapse(e.target.dataset.collapse);
};

那么你的 jsx 看起来像这样:

<Button
  className="article1-button"
  color="primary"
  data-collapse="article1" // A dataset param
  onClick={openCollapse}>
  <h3>Article 1</h3>
</Button>
<Collapse isOpen={openedCollapse === "article1"}>
    <Card className="card">
        <CardBody className="card-body">
            <Article2 />
        </CardBody>
    </Card>
</Collapse>

dataset info

您可以在切换 More Info 折叠时使用一个对象作为带有回调函数的状态,然后使用一个简单的字符串来确定当主 Collapse 打开时应打开哪篇文章,并且Button 在里面被点击了。

例如更新主折叠是否打开:

const toggleMoreInfo = () => {
  setState(prevState => {
    // this gives us access to the current state when setState is executed
    // then we can inverse a boolean when the More Info button is clicked
    return {
     article: "", // resets the open article
     moreInfoOpen: !prevState.moreInfoOpen // false => true || true => false
    }
  })
}

例如,更新应打开的文章:

 const handleArticleOpen = (article) => {
    setState((prevState) => 
      return {
      // keep whatever is in state as is by spreading it out (in this case, "moreInfoOpen" stays unchanged)
      ...prevState, // 
      // and just override the article with a passed in string
      article
    }));
  };

在处理耦合状态时,我喜欢在单个状态上使用对象,因为这样更容易使两组状态保持同步。有关演示和完整代码,请查看下面...


工作演示:


代码

import * as React from "react";
import { Button, Card, CardBody, Collapse } from "reactstrap";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";

export default function App() {
  const [state, setState] = React.useState({
    articleOpen: "",
    moreInfoOpen: false
  });
  const { article, moreInfoOpen } = state;

  const toggleMoreInfo = () => {
    setState((prevState) => ({
      article: "",
      moreInfoOpen: !prevState.moreInfoOpen
    }));
  };

  const handleArticleOpen = (article) => {
    setState((prevState) => ({
      ...prevState,
      article
    }));
  };

  return (
    <div className="app">
      <Button className="info-button" color="primary" onClick={toggleMoreInfo}>
        More Info
      </Button>
      <Collapse isOpen={moreInfoOpen}>
        <Card className="card">
          <CardBody className="card-body">
            <div className="section section-articles">
              <div className="articles-buttons">
                <Button
                  className="article2-button"
                  color="primary"
                  onClick={() => handleArticleOpen("2")}
                >
                  <h3>Article 2</h3>
                </Button>
                <Button
                  className="article1-button"
                  color="primary"
                  onClick={() => handleArticleOpen("1")}
                >
                  <h3>Article 1</h3>
                </Button>
              </div>

              <Collapse isOpen={article === "2"}>
                <Card className="card">
                  <CardBody className="card-body">
                    <div>Article 2</div>
                  </CardBody>
                </Card>
              </Collapse>
              <Collapse isOpen={article === "1"}>
                <Card className="card">
                  <CardBody className="card-body">
                    <div>Article 1</div>
                  </CardBody>
                </Card>
              </Collapse>
            </div>
          </CardBody>
        </Card>
      </Collapse>
    </div>
  );
}