如何在反应中只切换一个项目?

How to toggle only one item in react?

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

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

这个级别的显示没有问题,点击按钮就已经显示了第三级别的数据。

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

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

工作代码段如下,

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>

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

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

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>