【问题标题】:How to toggle only one item in react?如何在反应中只切换一项?
【发布时间】:2020-07-10 20:20:47
【问题描述】:

我正在使用 reactstrap Collapse 制作一个可折叠部分。

收到的数据是嵌套的,我需要在第二层显示折叠按钮,第三层会有数据显示。

这一层显示没有问题,点击按钮时已经在第三层显示数据了。

问题:点击任何按钮时,所有可折叠部分都会打开,而不是点击的部分。

要求:只有被点击部分的标记需要被显示,并且在再次点击按钮时它应该被折叠回来并且它不应该与任何其他项目有任何关系。 p>

工作片段如下,

const data = [{"orderId":1,"orderNo":"123", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3"]}] },
{"orderId":2,"orderNo":"456", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1","Token3"]}] },
{"orderId":3,"orderNo":"789", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3", "Token4"]}] }
]

const {Component, Fragment} = React;
const {Button, Collapse} = Reactstrap;

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false
    };
  }
  
  toggle = () =>
  this.setState(s => ({
    open: !s.open
  }));

  render() {
  console.log();
    return <div> 
      {
        data.map((levelOneItem, i) => {
          return(
          <div>
          <div> Order Id:  {levelOneItem.orderId} </div>
          {
            levelOneItem.orderParts.map((levelTwoItem, j) => {
               return(
                  <div>
                  <div> Order Part Id: {levelTwoItem.orderPartsId} </div>
                  <Button onClick={this.toggle}>Display Token</Button>
                  <Collapse isOpen={this.state.open}>
                    {
                       <div>
                        {levelTwoItem.regTokens.map((levelThreeItem, k) => {
                          return(<span> {levelThreeItem} </span>)
                        })
                     }
                       </div>
                    }
                  </Collapse>
                  </div>
               )
            })
          }
          </div>
          )
        })
      }
    </div>;
  }

}


ReactDOM.render(<Menu />, document.getElementById("root"));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>

<div id="root"></div>

请帮助我实现仅在所选项目上切换提供的嵌套数据的结果。

【问题讨论】:

    标签: javascript reactjs twitter-bootstrap collapse reactstrap


    【解决方案1】:

    为您的处理函数添加一个识别索引作为参数就可以了。

    this.state = {
      open: ''
    };
    
    toggle = idx => () => {
      this.setState(prevState => ({open: prevState.open === idx ? '' : idx}));
    }
    
    <Button onClick={this.toggle(i)}>
    <Collapse isOpen={open === i}>
    

    更新

    如果您希望它们独立,则需要一个数组来存储每个状态。

    this.state = {
      open: [0, 2]                                // Initial opened item's index
    };
    
    toggle = idx => () => {
      this.setState(prevState => ({
        open: this.state.open.includes(idx)       // check whether been expanded
          ? prevState.open.filter(x => x !== idx) // if yes, remove from list
          : [...prevState.open, idx]}             // if no, add to list
        ))
    }
    
    <Button onClick={this.toggle(i)}>
    <Collapse isOpen={open.includes(i)}>
    

    const data = [{"orderId":1,"orderNo":"123", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3"]}] },
    {"orderId":2,"orderNo":"456", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1","Token3"]}] },
    {"orderId":3,"orderNo":"789", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3", "Token4"]}] }
    ]
    
    const {Component, Fragment} = React;
    const {Button, Collapse} = Reactstrap;
    
    class Menu extends Component {
      constructor(props) {
        super(props);
        this.state = {
          open: [0, 2]  // Initial opened item's index
        };
      }
      
      toggle = idx => () => {
        this.setState(prevState => ({open: this.state.open.includes(idx) ? prevState.open.filter(x => x !== idx) : [...prevState.open, idx]})
      )}
      render() {
      const { open } = this.state;
        return <div> 
          {
            data.map((levelOneItem, i) => {
              return(
              <div>
              <div> Order Id:  {levelOneItem.orderId} </div>
              {
                levelOneItem.orderParts.map((levelTwoItem, j) => {
                   return(
                      <div>
                      <div> Order Part Id: {levelTwoItem.orderPartsId} </div>
                      <Button onClick={this.toggle(i)}>Display Token</Button>
                      <Collapse isOpen={open.includes(i)}>
                        {
                           <div>
                            {levelTwoItem.regTokens.map((levelThreeItem, k) => {
                              return(<span> {levelThreeItem} </span>)
                            })
                         }
                           </div>
                        }
                      </Collapse>
                      </div>
                   )
                })
              }
              </div>
              )
            })
          }
        </div>;
      }
    
    }
    
    
    ReactDOM.render(<Menu />, document.getElementById("root"));
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

    • 感谢您的回答.. 就像我在问题中提到的那样,它不应该与任何其他项目相关.. 这里切换应该只发生在单个项目上.. 在这个解决方案中,如果我先打开然后点击第二个,它首先关闭,这不是故意的..
    • @TestUser 我的意思是这样做,如果你需要他们独立,使用一个数组来保存状态,我会更新答案
    • 您能否在初始阶段添加所有可折叠按钮的详细信息(进入页面时无需单击)..我只想知道如何处理它..所以可以请您这样做以及其他详细信息..
    • 好吧,我认为你错过了索引 1,因此第二个没有打开。但我不能像这样对索引进行硬编码,如果我有 n 项目 levelOneItem.orderParts 我们如何声明像这??希望你明白我的意思..索引不能被硬编码,我不知道有多少项目可以折叠所以这不起作用..
    • @TestUser 你可以根据你的定制需求选择,最后做一个索引数组就可以了。我只是想对比较做一个解释,所以为了目的而离开[0, 2]而不是[0, 1, 2],最终的实现仍然不确定,因为没有相关的代码。如果您仍然面临进一步的问题,也许您可​​以打开一篇关于它的新帖子。喜欢How can I acquire the part of data based on the condition of ... and make an index array of it
    猜你喜欢
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 2019-01-16
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多