Как включить только один элемент в реакции? - PullRequest
1 голос
/ 30 марта 2020

Я делаю разборную секцию, используя реактивную ленту Свернуть.

Полученные данные вложены, и мне необходимо отобразить кнопку свертывания на втором уровне, а на третьем уровне будут отображаться данные.

Нет проблем на этом уровне отображения, и он уже отображает данные на третьем уровне при нажатии кнопки.

Проблема: При нажатии любой кнопки, все складные вместо открываемого раздела открывается раздел.

Требование: Необходимо отображать только токен (ы) выделенного раздела, и при повторном нажатии кнопки он должен быть свернут назад и должен не имеет никакого отношения к каким-либо другим элементам.

Рабочий фрагмент, как указано ниже,

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>

Пожалуйста, помогите мне добиться результата переключения только на выбранный элемент для предоставленных вложенных данных.

1 Ответ

0 голосов
/ 30 марта 2020

Добавьте индекс идентификации в качестве параметров для вашей функции-обработчика.

this.state = {
  open: ''
};

toggle = idx => () => {
  this.setState(prevState => ({open: prevState.open === idx ? '' : idx}));
}

<Button onClick={this.toggle(i)}>
<Collapse isOpen={open === i}>

Обновление

Если вы хотите, чтобы они были независимыми, вам нужно an Массив для хранения каждого статуса.

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>
...