展开/折叠所有数据

IT技术 javascript css reactjs accordion collapse
2021-05-11 08:46:59

我正在制作一个手风琴,当我们点击每个单独的项目时,它就会很好地打开或关闭。

现在我已经实现了全部展开或全部折叠选项,以使所有手风琴展开/折叠。

手风琴.js

  const accordionArray = [
    { heading: "Heading 1", text: "Text for Heading 1" },
    { heading: "Heading 2", text: "Text for Heading 2" },
    { heading: "Heading 3", text: "Text for Heading 3" }
  ];
  .

  .

  .
{accordionArray.map((item, index) => (
        <div key={index}>
          <Accordion>
            <Heading>
              <div className="heading-box">
                <h1 className="heading">{item.heading}</h1>
              </div>
            </Heading>
            <Text expandAll={expandAll}>
              <p className="text">{item.text}</p>
            </Text>
          </Accordion>
        </div>
      ))}

text.js就是我在做的动作如下打开手风琴的任何特定内容和代码的文件,

import React from "react";

class Text extends React.Component {
  render() {
    return (
      <div style={{ ...this.props.style }}>
        {this.props.expandAll ? (
          <div className={`content open`}>
            {this.props.render && this.props.render(this.props.text)}
          </div>
        ) : (
          <div className={`content ${this.props.text ? "open" : ""}`}>
            {this.props.text ? this.props.children : ""}
            {this.props.text
              ? this.props.render && this.props.render(this.props.text)
              : ""}
          </div>
        )}
      </div>
    );
  }
}

export default Text;

在这里通过this.props.expandAll我得到的值是 expandAll 是真还是假。如果它是真的,那么所有的手风琴都会得到这个类,className={`content open`}所以所有的都会被打开。

问题:

open级应用,但里面的文字内容不会被渲染。

所以这条线不起作用,

{this.props.render && this.props.render(this.props.text)}

要求:

如果单击全部展开/全部折叠按钮,则应分别打开/关闭所有手风琴。

无论之前打开/关闭手风琴,这都应该起作用。因此,如果全部展开,则它应该打开所有手风琴,否则即使之前打开/关闭它也需要关闭所有手风琴。

链接:

这是文件https://codesandbox.io/s/react-accordion-forked-sm5fw?file=/src/GetAccordion.js的链接,其中props实际上被传递了下来。

编辑react手风琴(分叉)

编辑:

如果我使用,{this.props.children}那么每个手风琴都会打开.. 没问题。

但是,如果我在单击特定项目时手动打开任何手风琴,那么如果我单击全部展开,则其已展开(预期)但如果我单击后退折叠所有选项,则并非所有手风琴都已关闭。我们之前打开的手风琴仍在打开状态.. 但这里的预期行为是一切都应该关闭。

3个回答

在你的文件 text.js 中

在第 9 行。请将之前的代码替换为: {this.props.children}

在沙箱中尝试过并为我工作。

/// 不能添加评论所以编辑答案本身。Accordian.js 包含您的钩子 expandAll 并且标题布尔值已经发生 GetAccordian.js。我建议将 expand all 移动到 GetAccordian.js 以便您可以控制这两个值。

在这种情况下 this.props.render 不是函数并且 this.props.text 未定义,请尝试替换此行

  <div className={`content open`}>
    {this.props.render && this.props.render(this.props.text)}
  </div>

这样:

  <div className={`content open`}>
   {this.props.children}
  </div>

编辑:// 其他解决方案是将 expandAll 属性传递给手风琴组件

  <Accordion expandAll={expandAll}>
    <Heading>
      <div className="heading-box">
        <h1 className="heading">{item.heading}</h1>
      </div>
    </Heading>
    <Text>
      <p className="text">{item.text}</p>
    </Text>
  </Accordion>

然后在 getAccordion.js

onShow = (i) => {
      this.setState({
        active: this.props.expandAll ? -1: i,
        reserve: this.props.expandAll ? -1: i
      });

      if (this.state.reserve === i) {
        this.setState({
          active: -1,
          reserve: -1
        });
      }
    };

    render() {
      const children = React.Children.map(this.props.children, (child, i) => {
        return React.cloneElement(child, {
          heading: this.props.expandAll || this.state.active === i,
          text: this.props.expandAll || this.state.active + stage === i,
          onShow: () => this.onShow(i)
        });
      });
      return <div className="accordion">{children}</div>;
    }
  };

基于@lissettdm 的回答,我不清楚为什么getAccordion并且accordion是两个独立的实体。您可能有一个非常有效的分离理由,但两个组件的状态是相互依赖的这一事实暗示它们可能更好地实现为一个组件。

Accordion 现在像以前一样直接控制其子项的状态,但不使用 getAccordion。切换 expandAll 现在也会重置单个项目的状态。

const NormalAccordion = () => {
  const accordionArray = [ //... your data ];

  const [state, setState] = useState({
    expandAll: false,
    ...accordionArray.map(item => false),
  });

  const handleExpandAll = () => {
    setState((prevState) => ({
      expandAll: !prevState.expandAll,
      ...accordionArray.map(item => !prevState.expandAll),
    }));
  };

  const handleTextExpand = (id) => {
    setState((prevState) => ({
      ...prevState,
      [id]: !prevState[id]
    }));
  };

  return (
    <>
      <div className="w-full text-right">
        <button onClick={handleExpandAll}>
          {state.expandAll ? `Collapse All` : `Expand All`}
        </button>
      </div>
      <br />
      {accordionArray.map((item, index) => (
        <div key={index}>
          <div className="accordion">
            <Heading handleTextExpand={handleTextExpand} id={index}>
              <div className="heading-box">
                <h1 className="heading">{item.heading}</h1>
              </div>
            </Heading>
            <Text shouldExpand={state[index]}>
              <p className="text">{item.text}</p>
            </Text>
          </div>
        </div>
      ))}
    </>
  );
};

Heading 传回索引,以便父组件知道要关闭哪个项目。

class Heading extends React.Component {
  handleExpand = () => {
    this.props.handleTextExpand(this.props.id);
  };


  render() {
    return (
      <div
        style={ //... your styles}
        onClick={this.handleExpand}
      >
        {this.props.children}
      </div>
    );
  }
}

Text 只关心一个 prop 来确定它是否应该显示展开内容。

class Text extends React.Component {
  render() {
    return (
      <div style={{ ...this.props.style }}>
        <div
          className={`content ${this.props.shouldExpand ? "open" : ""}`}
        >
          {this.props.shouldExpand ? this.props.children : ""}
        </div>
      </div>
    );
  }
}