react-bootstrap Аккордеон не сворачивается с картой

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

В одном файле у меня есть:

var items = this.state.contents.map(function(content, index) {
  return <Content {...content}, key={index}/>
};

return (
  <Accordion>
    {items}
  </Accordion>
);

В другом файле под названием Content у меня есть:

return(
  <Panel header={this.props.header} eventKey={this.props.key}>
    {this.props.body}
  </Panel>
);

Когда у меня есть аккордеон и панель в одном файле, они работают. Но когда я создаю панель с помощью карты после разделения их на два файла, похоже, она не разрушается.


person de rigueur    schedule 06.03.2015    source источник
comment
да, такая хрень не работает. Я не знаю, как решить эту проблему с помощью однофайлового подхода   -  person kurumkan    schedule 19.09.2016


Ответы (5)


Вот решение

<Accordion>
  {this.item.map(item =>
     <AcPanel key={item.id} item={item} eventKey={item.id} />
  )}
</Accordion>

В классе AcPanel используйте {... this.props} для получения всех свойств и назначения значений в родительском классе, как я использовал "eventKey = {item.id}".

<Panel header={`Collapsible Group Item`} bsClass='class-name' {...this.props}>
content here
</Panel>
person Lalit Joshi    schedule 13.02.2017

Для тех, кто использует Accordion.Toggle, вот как я заставил аккордеон свернуть на карте.

В родительском компоненте Accordion добавьте в состояние значение activeKey. Создайте функцию для обработки активного изменения ключа, которое будет передаваться во время вашей карты каждому дочернему компоненту аккордеона. Обязательно привяжите эту функцию к родительскому компоненту.

this.state = {
  items = []
  activeKey: ''
}

handleActiveKeyChange = activeKey => {
  if (this.state.activeKey === activeKey) {
    //allows us to close expanded item by clicking its toggle while open
    activeKey = -1
  }
  this.setState({ activeKey })
}

Передайте активное состояние ключа и функцию соответственно в методе рендеринга:

<Accordion activeKey={this.state.activeKey}>
  {this.state.items.map((item, index) => (
    <Item eventKey={index} handleActiveKeyChange={this.handleActiveKeyChange} />
  ))}
</Accordion

В переключателе Accordion вашего дочернего элемента (item) добавьте переданную функцию и реквизиты:

<Card>
  <Card.Header>
    <Accordion.Toggle
      eventKey={this.props.eventKey}
      onClick={() => this.props.handleActiveKeyChange(this.props.eventKey)}
    >
      //+ icon here
    </Accordion.Toggle>
  </Card.Header>
  //card content here 
</Card
person Ethan    schedule 11.12.2019
comment
Большое спасибо @Ethan, это лучшее решение с тех пор, как неделю назад я пытаюсь решить эту проблему и искал во всей сети, пока не получу это Еще раз спасибо - person Saddam Mohsen; 24.02.2020

Я нашел решение, которое позволяет использовать компонент в отдельном файле.

Я решил, что проблема связана с тем, что Accordion не может передать некоторые реквизиты Panel, потому что вместо этого они переходят в компонент упаковки, поэтому я попытался собрать все реквизиты, которые не были моими, и передать их панели:

// make sure you have all your own props specified before ...props
// so that they can't mess up the panel.
const { body, ...props } = this.props

return(
  <Panel {...props}>
    {body}
  </Panel>
);

Если вы хотите указать какие-либо реквизиты в Panel, убедитесь, что они идут после собранных реквизитов, чтобы иметь приоритет над любыми значениями по умолчанию:

const { body, ...props } = this.props

return(
  <Panel {...props}
         bsStyle="info">
    {body}
  </Panel>
);

Если вы выберете какие-либо имена свойств, такие же, как и все, что Accordion передает Panel, вы можете что-то заткнуть и сломать - если вас это беспокоит, должно быть просто следовать коду и смотреть, что передается.

person David Mason    schedule 05.12.2016

response-bootstrap, кажется, жалуется, если дочерние элементы Accordion не являются панелями, и, обернув Panel внутри моего класса Content, я делал именно это.

Чтобы решить эту проблему, мне пришлось отойти от соглашения React. Вместо того, чтобы создавать класс Content, я создал другой файл js, а не файл response.js. Обращаясь с этим файлом как с обычным файлом js, я смог вызвать функцию внутри этого файла, которая сопоставляет каждый this.state.contents и возвращает объект Panel.

Весь этот файл вернет массив класса Panel.

person de rigueur    schedule 13.03.2015
comment
@ArslArsl, оказывается, можно сделать с помощью обычного компонента. Смотрите мой ответ. - person David Mason; 05.12.2016

Самый простой способ сделать это - создать условие внутри параметра eventKey.

 <Card key={item.id}> 
    <Card.Header>
      <Accordion.Toggle as={Button} variant="link" eventKey={index === 0 ? '0' : index}>
        {item.title} 
      </Accordion.Toggle>
    </Card.Header>
    <Accordion.Collapse eventKey={index === 0 ? '0' : index}>
      <Card.Body>
             CARD BODY
      </Card.Body>
    </Accordion.Collapse>
  </Card>
person TonyLoops    schedule 08.10.2020