【问题标题】:Using Reactstrap: How to toggle only one Collapse at a time?使用 Reactstrap:如何一次只切换一个 Collapse?
【发布时间】:2021-07-13 05:30:04
【问题描述】:

我正在使用 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>

【问题讨论】:

    标签: javascript reactjs jsx reactstrap


    【解决方案1】:

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

    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>
    

    【讨论】:

      【解决方案2】:

      您可以使用一种状态来控制所有折叠。

      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

      【讨论】:

        【解决方案3】:

        您可以在切换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>
          );
        }
        

        【讨论】:

          猜你喜欢
          • 2021-01-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多