Bootstrap выпадающие в ReactJS, только один открытый за один раз - PullRequest
0 голосов
/ 01 октября 2018

У меня есть страница, содержащая несколько карт начальной загрузки, и каждая карта является компонентом, и каждый нижний колонтитул карты также является компонентом.Нижний колонтитул содержит кнопки.При нажатии на кнопку открывается раскрывающийся список, как показано ниже:

enter image description here

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

enter image description here

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

Требование: Когда я нажимаю на любой элемент внутри выпадающего меню, соответствующий раскрывающийся список должен быть закрыт

Моя архитектура похожа на ниже

enter image description here

ДОМАШНЯЯ СТРАНИЦА КОМПОНЕНТ-КОД-НАЧАЛО

class HomePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      items: [],
      activatedIdStoredInParent: ""
    };
  }
  toggleCountersMenu = (name) => {
    var name1 = name;
    this.setState((prevState) => {
      return {
        activatedIdStoredInParent: name1
      }
    });
  } 

  render() {
   
    const products = this.state.items.map((item, index) => {     
      return <div>
        <Card
          product={item}
          activatedIdStoredInParent={this.state.activatedIdStoredInParent}
          toggleCountersMenu={this.toggleCountersMenu}
        >
        </Card>;
      </div>
    });

    return (
      <div>
        <div className="card-columns">
          {products}
        </div>
      </div >
    );
  }
}

export default HomePage;

КОМПОНЕНТНЫЙ КОД ГЛАВНОЙ СТРАНИЦЫ - КОНЕЦ

КОМПОНЕНТНЫЙ КОД КАРТЫ - СТАРТ

class Card extends React.Component {
    handleActionClick = (name) => {
        this.props.toggleCountersMenu(name);
    }
    render() {
        return (
            <div key={this.props.product.name}>
                <CardHeader product={this.props.product}  />
                <CardBody product={this.props.product}  />
                <CardFooter
                    product={this.props.product}                    
                    onActionItemClick={this.handleActionClick}
                    activatedIdStoredInParent={this.props.activatedIdStoredInParent}
                />
            </div>
        );
    }
}

export default Card;

КОМПОНЕНТНЫЙ КОД ФУТБОЛА КАРТЫ - НАЧАЛО

class CardFooter extends React.Component {

    handleActionItemClick = (name) => {
        this.props.onActionItemClick(name);
    }

    render() {
        console.log('Card Footer Drop Down comp rendered');
        return (
            <div className=" card-footer text-center">
                <ButtonDropdown text="F" className="danger"
                    product={this.props.product}
                    onActionItemClick={this.handleActionItemClick}
                    activatedIdStoredInParent={this.props.activatedIdStoredInParent}
                ></ButtonDropdown>            
            </div>
        );
    }
}

export default CardFooter;

ButtonDropdown КОМПОНЕНТНЫЙ КОД - СТАРТ

class ButtonDropdown extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            open: false,
            show: ' none',
            localActivatedId: 'none'
        }
    }
    toggleOpen = (e) => {
        var name = e.target.name;

        this.setState((prevState, props) => {
            var item = {
                localActivatedId: name
            }
            if (props.activatedIdStoredInParent === name) {
                if (prevState.show === ' show') {
                    item.show = ' none';
                }
                else {
                    item.show = ' show';
                }
            }
            return item;
        });
        this.props.onActionItemClick(name);
    }

    numberClick = (e) => {
        var qty = e.target.innerText;
        this.setState((prevState, props) => {
            var item = {
                show: ' none'
            }
            return item;
        });
    }
    render() {
        return (
            <div className="btn-group" >
                <button type="button" className={`btn btn-${this.props.className}  mr-1`} name={this.props.product.name + '$$' + this.props.text} onClick={this.toggleOpen}>
                    {this.props.text} (classAdded={this.state.show})
                </button>
                
                <div className={`dropdown-menu ${this.state.show}`}>
                    <span className="dropdown-item cursor-pointer " onClick={this.numberClick}>
                        -1
                    </span>
                    <span className="dropdown-item cursor-pointer" onClick={this.numberClick}>
                        -2
                    </span>
                </div>
            </div>



        );
    }
}

export default ButtonDropdown;

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

enter image description here

Я хотел бы знать, правильна ли моя архитектура ... Я не использую Redux / Flux и т. Д ..

1 Ответ

0 голосов
/ 04 октября 2018

Вы можете использовать жизненный цикл componentDidUpdate, чтобы обновить свойство вашего штата, открывающее раскрывающийся список.Я не знаю, является ли это свойство open или show отображением содержимого раскрывающегося списка, но вот моя логика.

class ButtonDropdown extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      // 
    };
  }

  componentDidUpdate(prevProps) {
    const name = this.props.product.name + '$$' + this.props.text;

    if (prevProps.activatedIdStoredInParent !== this.props.activatedIdStoredInParent && this.props.activatedIdStoredInParent !== name) {
      this.closeDropDown();
    }
  }

  closeDropDown = () => this.setState({ isOpen: false });

  toggleOpen = (e) => {
    //
  }

  numberClick = (e) => {
   //
  }

  render() {
   //
  }
}

export default ButtonDropdown;
...