我有以下对话框组件:
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>
);
}
}
如何从父组件打开该对话框并确保关闭对话框也能正常工作?这是我的尝试
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>
);
}
}
所以我不确定我是否真的必须在子/父/母中都保留对话状态,以及如何正确地从父/母中打开对话状态。
答案 0 :(得分:1)
无论父级中登录对话框是否打开,都必须保持状态。将打开/关闭状态传递给子项,然后通过回调将其通过props关闭向子项的对话框。
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>
);
}
}
此组件不需要任何状态管理,因为我们在父级中对其进行管理。我们可以这样制作:
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>
);
希望这会有所帮助!
答案 1 :(得分:0)
您可以在MainAppBar组件内定义handleClose()或等效的事件处理程序,并将其传递给子级。它可以管理Parent上的状态变量(真/假),并将该布尔值传递到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>
);
}
}
然后:
class LoginDialog extends React.Component {
render() {
return (
<div>
<Dialog
open={this.props.open}
onClose={() => this.props.toggle} //not sure what this listener does, but im assuming you want to close it
>
<DialogActions>
<Button onClick={() => this.props.toggle} color="primary">
Cancel
</Button>
<Button onClick={() => this.props.toggle} color="primary">
Subscribe
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
答案 2 :(得分:0)
如果让父组件管理对话框的状态,则可以将其完全控制,同时将控制功能传递给对话框元素本身:
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>
);
}
}
class LoginDialog extends React.Component {
render() {
return (
<div>
<Dialog
open={this.props.isOpen}
onClose={this.props.closeDialog}
>
<DialogActions>
<Button onClick={this.props.closeDialog} color="primary">
Cancel
</Button>
<Button onClick={this.props.closeDialog} color="primary">
Subscribe
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
答案 3 :(得分:0)
我将采用与其他答案不同的方法,并且仅在需要时才包含LoginDialog
。
我们现在可以使LoginDialog
成为功能组件,并使lift the state up成为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>
);
}
}
从closeDialog
接收Parent
作为道具,并将其传递给Child
组件
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>
);