Reactjs 如何处理对话框组件外部的对话框状态?

Reactjs 如何处理对话框组件外部的对话框状态?,reactjs,Reactjs,我有以下对话框组件: class LoginDialog extends React.Component { state = { open: false, }; openDialog = () => { this.setState({ open: true }); }; handleClose = () => { this.setState({ open: false }); }; render() { return

我有以下对话框组件:

class LoginDialog extends React.Component {
  state = {
    open: false,
  };

  openDialog = () => {
    this.setState({ open: true });
  };

  handleClose = () => {
    this.setState({ open: false });
  };

  render() {
    return (
      <div>
        <Dialog
          open={this.state.open}
          onClose={this.handleClose}
        >
          <DialogActions>
            <Button onClick={this.handleClose} color="primary">
              Cancel
            </Button>
            <Button onClick={this.handleClose} color="primary">
              Subscribe
            </Button>
          </DialogActions>
        </Dialog>
      </div>
    );
  }
}
classlogindialog扩展了React.Component{
状态={
开:错,
};
openDialog=()=>{
this.setState({open:true});
};
handleClose=()=>{
this.setState({open:false});
};
render(){
返回(
取消
订阅
);
}
}
如何从父组件打开该对话框并确保“关闭”对话框也可以工作?这是我的尝试

class MainAppBar extends React.Component {
    state = {
    openLoginDialog: false,
    openRegisterDialog: false
    };
    render() {
        return (
            <div>
                <Button color="inherit" onClick={this.state.openLoginDialog}>Login</Button>
                )}
                <LoginDialog /*not sure how to pass here openLoginDialog*//>
            </div>
        );
    }
}
类MainAppBar扩展了React.Component{
状态={
openLoginDialog:错误,
openRegisterDialog:false
};
render(){
返回(
登录
)}
);
}
}

因此,我不确定是否必须在子/父级中保留对话框状态,以及如何从父级正确打开它。

您可以在MainAppBar组件中定义handleClose()或等效的事件处理程序,并将其传递给子级。它可以管理父级上的状态变量(真/假),并将该布尔值传递到LoginDialog栏,以确定它们是否应该打开。这样子级的状态将由父级管理

class MainAppBar extends React.Component {
    state = {
    openLoginDialog: false,
    openRegisterDialog: false
    };

    toggleDialog = () => {
       this.setState((prevState) => {
          return{
             openLoginDialog: !prevState.openLoginDialog
          }
       })
    }

    render() {
        return (
            <div>
                <Button color="inherit" onClick={this.state.openLoginDialog}>Login</Button>
                )}
                <LoginDialog open={this.state.openLoginDialog} toggle={this.toggleDialog}/>
            </div>
        );
    }
}
类MainAppBar扩展了React.Component{
状态={
openLoginDialog:错误,
openRegisterDialog:false
};
切换对话框=()=>{
this.setState((prevState)=>{
返回{
openLoginDialog:!prevState.openLoginDialog
}
})
}
render(){
返回(
登录
)}
);
}
}
然后:

classlogindialog扩展了React.Component{
render(){
返回(
this.props.toggle}//不确定此侦听器的功能,但我假设您要关闭它
>
this.props.toggle}color=“primary”>
取消
this.props.toggle}color=“primary”>
订阅
);
}
}

如果让父组件管理对话框的状态,则可以允许它完全控制对话框,同时将控制功能传递给对话框元素本身:

class MainAppBar extends React.Component {
        constructor(props) {
            this.state = {
                openLoginDialog: false,
                openRegisterDialog: false
            };
        }

        closeDialog() {  // This method will be passed to the dialog component
            this.setState({
                openLoginDialog: false
            });
        }

        render() {
            return (
                <div>
                    <Button color="inherit" onClick={this.state.openLoginDialog}>Login</Button>
                    )}
                    <LoginDialog isOpen={this.state.openLoginDialog} closeDialog={this.closeDialog}>
                </div>
            );
        }
    }
类MainAppBar扩展了React.Component{
建造师(道具){
此.state={
openLoginDialog:错误,
openRegisterDialog:false
};
}
closeDialog(){//此方法将被传递给对话框组件
这是我的国家({
openLoginDialog:错误
});
}
render(){
返回(
登录
)}
);
}
}

classlogindialog扩展了React.Component{
render(){
返回(
取消
订阅
);
}
}

无论登录对话框在父级中是否打开,您都必须保持该状态。将打开/关闭状态传递给子级,并通过道具将关闭对话框的回调传递给子级

class MainAppBar extends React.Component {
  state = {
    openLoginDialog: false,
    openRegisterDialog: false
  };

  openLoginDialog = () => {
    this.setState({
      openLoginDialog: true
    });
  };

  closeLoginDialog = () => {
    this.setState({
      openLoginDialog: false
    });
  };
  render() {
    return (
      <div>
        <Button color="inherit" onClick={() => this.openLoginDialog()}>
          Login
        </Button>
        )}
        <LoginDialog
          closeLoginDialog={this.closeLoginDialog}
          isLoginDialogOpen={this.state.openLoginDialog}
        />
      </div>
    );
  }
}
类MainAppBar扩展了React.Component{
状态={
openLoginDialog:错误,
openRegisterDialog:false
};
openLoginDialog=()=>{
这是我的国家({
openLoginDialog:对
});
};
closeLoginDialog=()=>{
这是我的国家({
openLoginDialog:错误
});
};
render(){
返回(
this.openLoginDialog()}>
登录
)}
);
}
}
这个组件不需要任何状态管理,因为我们在父级中管理它。我们可以通过这种方式使产品变得纯净:

const LoginDialog = props => (
  <div>
    <Dialog open={props.isLoginDialogOpen} onClose={props.closeLoginDialog}>
      <DialogActions>
        <Button onClick={props.closeLoginDialog} color="primary">
          Cancel
        </Button>
        <Button onClick={props.closeLoginDialog} color="primary">
          Subscribe
        </Button>
      </DialogActions>
    </Dialog>
  </div>
);
const LoginDialog=props=>(
取消
订阅
);

希望这是有帮助的

我将采取与其他答案不同的方法,只在需要时包含
LoginDialog

现在,我们可以将
LoginDialog
作为一个功能组件,并添加到
Parent
组件。现在,我们的
LoginDialog
更简单、更易于测试,并且不依赖于任何东西

class Parent extends React.Component {
  state = {
    isOpen: false,
  };

  // No need to use open and close handler because if the modal
  // is open another execute of the function will close it
  // this way we can still toggle it from the button that's opening the Dialog
  toggleDialog = () => {
    this.setState(prevState => ({
      open: !prevState.open,
    }));
  };

  // if you want make the handler more flexible you can write it like this
  // make it a toggle by default with an optional nextState to
  // make it more flexible
  dialogStateHandler = (nextState) => () => {
    this.setState(prevState => ({
      open: nextState || !prevState.open,
    }));
  };
  // to use this handler you will need to invoke it and passing
  // in the nextState or without to make it toggle
  // onClick={this.dialogStateHandler(true / false || without args to toggle)}

  render() {
    const { isOpen } = this.state;

    return (
      <div>
        <button onClick={this.toggleDialog}>Toggle</button>
        {/* include the Dialog component only when its open */}
        {isOpen && <LoginDialog closeDialog={this.toggleDialog} />}
      </div>
    );
  }
}

可以在父组件中管理对话框的可见性状态,并将控制对话框的函数作为属性传递给子组件。然后可以从子元素和父元素控制它。
const LoginDialog = props => (
  <div>
    <Dialog open={props.isLoginDialogOpen} onClose={props.closeLoginDialog}>
      <DialogActions>
        <Button onClick={props.closeLoginDialog} color="primary">
          Cancel
        </Button>
        <Button onClick={props.closeLoginDialog} color="primary">
          Subscribe
        </Button>
      </DialogActions>
    </Dialog>
  </div>
);
class Parent extends React.Component {
  state = {
    isOpen: false,
  };

  // No need to use open and close handler because if the modal
  // is open another execute of the function will close it
  // this way we can still toggle it from the button that's opening the Dialog
  toggleDialog = () => {
    this.setState(prevState => ({
      open: !prevState.open,
    }));
  };

  // if you want make the handler more flexible you can write it like this
  // make it a toggle by default with an optional nextState to
  // make it more flexible
  dialogStateHandler = (nextState) => () => {
    this.setState(prevState => ({
      open: nextState || !prevState.open,
    }));
  };
  // to use this handler you will need to invoke it and passing
  // in the nextState or without to make it toggle
  // onClick={this.dialogStateHandler(true / false || without args to toggle)}

  render() {
    const { isOpen } = this.state;

    return (
      <div>
        <button onClick={this.toggleDialog}>Toggle</button>
        {/* include the Dialog component only when its open */}
        {isOpen && <LoginDialog closeDialog={this.toggleDialog} />}
      </div>
    );
  }
}
const LoginDialog = ({ closeDialog }) => (
  <div>
    <Dialog
      closeDialog={closeDialog}
    >
      <DialogActions>
        <Button onClick={closeDialog} color="primary">
          Cancel
        </Button>
        <Button onClick={closeDialog} color="primary">
          Subscribe
        </Button>
      </DialogActions>
    </Dialog>
    )}
  </div>
);