Как автоматически закрыть диалоговое окно при открытии другого в React - PullRequest
0 голосов
/ 03 августа 2020

TopButtonsBarComponent

I am making a react app that has a navbar as pictured above. The navbar is a component called "TopButtonsBar". Rendered inside this TopButtonsBar component are a component for every button picture above. These components from left to right are InfoButton, NotificationsButton, and so on. Each of the button components manage their own state which dictates whether a dialog box of a given button should be shown or not. Here is what the buttons component look like individually, using the InfoButton component as an example.

    export default class InfoButton extends React.Component{
    
    constructor(props){
        super(props);
        this.state = {
            isDialogueOpen:false,
            isHoveringOver:false
        };
        this.handleOpenDialogue = this.handleOpenDialogue.bind(this);
        this.handleHoverOver = this.handleHoverOver.bind(this);
    }
    
    **handleOpenDialogue = (e) => {
        e.preventDefault();
        this.setState((prevState) => ({
            isDialogueOpen:!prevState.isDialogueOpen
        }));
    }**
    handleHoverOver = (e) => {
        e.preventDefault();
        if(!this.state.isDialogueOpen){
            this.setState((prevState) => ({
                isHoveringOver:!prevState.isHoveringOver
            }));
        }
    }
    
    render(){
        return(
             Информация {this.state.isHoveringOver &&! this.state.isDialogueOpen && } ** {this.state.isDialogueOpen && } ** )}} 

Важные биты * заключены в звездочки *. Этот лог c отлично работает на индивидуальном уровне кнопок. Я пытаюсь сделать следующее: если, как показано на рисунке выше, выбрана кнопка уведомлений о сообщениях, если я нажму кнопку информации, я хочу, чтобы кнопка уведомлений о сообщениях закрывалась одновременно с открытием кнопки информации. Однако мне не удалось понять, как мне перенастроить состояние. Должен ли компонент TopButtonsBar содержать информацию о состоянии, если какая-либо из кнопок закрыта? Если да, то как я могу go пересмотреть способ открытия кнопок (и должен ли отдельный компонент кнопки управлять этим состоянием или нет). Кроме того, я не использую никаких диспетчеров состояний, таких как Redux, Hooks и др. c. Спасибо!

1 Ответ

1 голос
/ 04 августа 2020

Один из способов решить эту проблему - иметь флаги (как в isDialogueOpen) для всех дочерних компонентов (InfoButton, NotificationButton и так далее) в состоянии родительского компонента (TopButtonsBar).

TopButtonsBar. js

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

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


// adding some constants here
const INFO_BUTTON = 'INFO_BUTTON';
const NOTIFICATION_BUTTON = 'NOTIFICATION_BUTTON';

export default class TopButtonsBar extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         ...
         // adding this state to point out which dialogue is open
         selectedDialogue: null
      }
   }
   
   handleOpenDialogue = (e, selectedDialogue) => {
      e.preventDefault();
      if (selectedDialogue === this.state.selectedDialogue) {
         // close dialogue if already open
         this.setState({selectedDialogue: null});
      } else {
         // else open this dialogue
         this.setState({selectedDialogue});
      }
   }
   
   ....
   render() {
      return (
          ....
          <InfoButton
               isDialogueOpen={this.state.selectedDialogue === INFO_BUTTON}
               handleOpenDialogue={(e) => handleOpenDialogue(e, INFO_BUTTON)}
               ...
          />
          <NotificationButton
               isDialogueOpen={this.state.selectedDialogue === NOTIFICATION_BUTTON}
               handleOpenDialogue={(e) => handleOpenDialogue(e, NOTIFICATION_BUTTON)}
               ...
          />
      )
   }
}

InfoButton. js

Теперь, когда мы передаем состояние и его функцию обработки из компонента TopButtonsBar в качестве свойств, мы можем вызывать их непосредственно в InfoButton и NotificationButton, без требуются любые соответствующие местные штаты.

export default class InfoButton extends React.Component{
    
    constructor(props){
        super(props);
        this.state = {
            // removing the state from here
            isHoveringOver:false
        };
        this.handleHoverOver = this.handleHoverOver.bind(this);
    }
    
    // removing the handleOpenDialogue function here

    ...
    
    render(){
        return(
            <div className="navbar-button">
                <img 
                    onMouseOver={this.handleHoverOver} 
                    onMouseLeave={this.handleHoverOver}
                    // calling handleOpenDialogue from props
                    onClick={this.props.handleOpenDialogue}
                    ...
                />
                // using isDialogueOpen from props now
                {this.state.isHoveringOver && !this.props.isDialogueOpen && <InfoRollover />}
                {this.props.isDialogueOpen && <InfoDialogue />}
            </div>
        )
    }
}
...