【问题标题】:How to close a dialog box automatically when opening a different one in React在 React 中打开另一个对话框时如何自动关闭一个对话框
【发布时间】:2020-11-23 22:43:30
【问题描述】:

我正在制作一个带有导航栏的反应应用程序,如上图所示。导航栏是一个名为“TopButtonsBar”的组件。在此 TopButtonsBar 组件内呈现的是上面每个按钮图片的组件。这些组件从左到右依次是InfoButton、NotificationsButton等。每个按钮组件都管理自己的状态,该状态指示是否应显示给定按钮的对话框。以下是按钮组件的外观,以 InfoButton 组件为例。

    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(
            <div className="navbar-button">
                <img 
                    onMouseOver={this.handleHoverOver} 
                    onMouseLeave={this.handleHoverOver} 
                    onClick={this.handleOpenDialogue}
                    src={this.state.isHoveringOver?infoButtonHovered:infoButtonNotHovered} alt="Info"
                />
                {this.state.isHoveringOver && !this.state.isDialogueOpen && <InfoRollover />}
                **{this.state.isDialogueOpen && <InfoDialogue />}**
            </div>
        )
    }
}

重要的位是 * 用星号括起来的 *。此逻辑在按钮单独级别上运行良好。我要做的是:如果,如上图所示,选择了消息通知按钮,如果我单击信息按钮,我希望消息通知按钮在信息按钮打开的同时关闭。但是,我在概念化我应该如何重新配置​​状态方面一直没有成功。如果任何按钮已关闭,TopButtonsBar 组件是否应该保存有关状态的信息?如果是这样,我将如何重新处理按钮的打开方式(以及单个按钮组件是否应该控制该状态)。另外,我没有使用任何状态管理器,例如 Redux、Hooks 等。 谢谢!

【问题讨论】:

    标签: reactjs dialog modal-dialog state


    【解决方案1】:

    解决此问题的一种方法是将所有子组件(InfoButtonNotificationButton 等)的标志(如 isDialogueOpen)置于父组件的状态 (TopButtonsBar)。

    TopButtonsBar.js

    我将首先添加一些用于标识每个对话框的常量。之后,我们可以声明一个状态,它会指向打开的对话框。

    只需按照下面代码中的 cmets 进行操作即可更好地理解。

    
    // 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 组件传递状态及其处理函数作为道具,我们可以直接在InfoButtonNotificationButton 中调用它们,不需要任何相关的本地状态。

    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>
            )
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-30
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多