展开/折叠所有数据 [英] Expand/Collapse all data

查看:82
本文介绍了展开/折叠所有数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


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


Accordion.js

  const手风琴数组= [
{标题:标题1,文本:标题1的文本; },
{标题:标题2,文本:标题2的文本; },
{标题:标题3,文本:标题3的文本; }
];





{accordionArray.map((item,index)= >>(
< div键= {index}>
<手风琴>
< Heading>
< div className =标题框>
< h1 className =标题> {item.heading}< / h1>
< / div>
< / Heading>
< Text expandAll = {expandAll}>
< p className =" text> {item.text}< / p>
< / Text>
< / Accordion>
< / div>
))}

text.js 是一个文件,在该文件中,我将按照以下步骤打开手风琴的任何特定内容和代码,

  import从反应中反应; 

类文本扩展React.Component {
render(){
return(
< div style = {{....... 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>
);
}
}

导出默认文本;

在这里通过 this.props.expandAll expandAll是true还是false。如果为真,则所有手风琴都将获得 className = {`content open`} 类,因此所有手风琴都将被打开。


问题:


已应用 open 类,但未呈现内部文本内容。


因此该行不起作用

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

要求:


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


这应该无关紧要因此,如果全部展开,那么它应该打开所有手风琴,否则就需要关闭所有手风琴,即使之前已打开/关闭它也是如此。


链接:


这是文件


编辑:


如果我使用 {this.props.children} 然后打开每个手风琴。没有问题。


但是如果我在单击特定项目时手动打开任何手风琴然后,如果我单击全部展开,则它的expanded(expected),但是如果我单击返回全部折叠选项,则并非全部。手风琴关闭。。我们之前打开的手风琴仍处于打开状态。

解决方案

建立在@lissettdm答案的基础上,我不清楚为什么 getAccordion 手风琴是两个单独的实体。您可能有很充分的理由进行分离,但是两个组件的状态是相互依存的事实提示它们可能会更好地实现为一个组件。


手风琴现在控制着像以前一样直接是孩子,但不使用getAccordion。

  const NormalAccordion =()=>现在,切换expandAll也会重置各个项目的状态。 {
const AccordionArray = [// ...您的数据];

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键= {index}>
< div className = accordion>
<标题handleTextExpand = {handleTextExpand} id = {index}>
< div className =标题框>
< h1 className =标题 {item。标题}< / h1>
< / div>
< / Heading>
<文本shouldExpand = {state [index]}>
< p className =文本> {item.text}< / p>
< /文本>
< / div>
< / div>
)) }
< />
);
};

标题返回索引,以便父组件知道要关闭哪个项目。

  class标题扩展了React.Component {
handleExpand =()=> {
this.props.handleTextExpand(this.props.id);
};


render(){
return(
< div
style = {// ...您的样式}
onClick = {this.handleExpand}
>
{this.props.children}
< / div>
);
}
}

文本只关心一个道具,以确定它是否应该显示扩展内容

 类文本扩展了React.Component {
render(){
return(
< div样式= {{... this.props.style}}>
< div
className = {`content $ {this.props.shouldExpand? open:}` }
>
{this.props.shouldExpand?this.props.children:}
< / div>
< / div>
);
}
}


I am making a Accordion and when we click each individual item then its opening or closing well.

Now I have implemented expand all or collapse all option to that to make all the accordions expand/collapse.

Accordion.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>
      ))}

And text.js is a file where I am making the action to open any particular content of the accordion and the code as follows,

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;

Here via this.props.expandAll I am getting the value whether the expandAll is true or false. If it is true then all accordion will get the class className={`content open`} so all will gets opened.

Problem:

The open class is applied but the inside text content is not rendered.

So this line doesn't work,

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

Requirement:

If expand all/collapse all button is clicked then all the accordions should gets opened/closed respectively.

This should work irrespective of previously opened/closed accordion.. So if Expand all then it should open all the accordion or else needs to close all accordion even though it was opened/closed previously.

Links:

This is the link of the file https://codesandbox.io/s/react-accordion-forked-sm5fw?file=/src/GetAccordion.js where the props are actually gets passed down.

Edit:

If I use {this.props.children} then every accordion gets opened.. No issues.

But if I open any accordion manually on click over particular item then If i click expand all then its expanded(expected) but If I click back Collapse all option then not all the accordions are closed.. The ones which we opened previously are still in open state.. But expected behavior here is that everything should gets closed.

解决方案

Building off of @lissettdm answer, it's not clear to me why getAccordion and accordion are two separate entities. You might have a very valid reason for the separation, but the fact that the two components' states are interdependent hints that they might be better implemented as one component.

Accordion now controls the state of it's children directly, as before, but without using getAccordion. Toggling expandAll now resets the states of the individual items as well.

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 passes back the index so the parent component knows which item to turn off.

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 only cares about one prop to determine if it should display the expand content.

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>
    );
  }
}

这篇关于展开/折叠所有数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆