#javascript #reactjs
Вопрос:
Я экспериментирую с модалом, который открывается, когда я нажимаю на кнопку, но он открыт в начале и никогда не закрывается.
Как убедиться, что он закрыт при монтировании и закрывается, когда я нажимаю за пределами окна сообщения ?
Я адаптирую модальную демонстрацию из материального ядра:
import React, { Component } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Modal from '@mui/material/Modal';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4
};
export class Contact extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
setOpen: false
}
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
}
static displayName = Contact.name;
handleOpen() { this.setState({ setOpen: true }); }
handleClose() { this.setState({ setOpen: false }); }
render() {
return(
<div>
<div className="center">
<Button onClick={() => this.handleOpen()}>Contact us</Button>
</div>
<Modal open={() => this.state.open()} onClose={()=> this.handleClose()}
aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description">
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Contact us
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Contact us at hello @ mycompany.com
</Typography>
</Box>
</Modal>
</div >
);
}
}
Ответ №1:
Вы использовали и обновляли два разных значения состояния open
и setOpen
. Вот почему она открывалась и никогда не закрывалась. Обновил свой код в песочнице. Другая проблема заключалась в том, что вы использовали open={() => this.state.open()}
для модального состояния, которое всегда возвращало значение true. Вместо этого вам нужно использовать open={this.state.open}
вот полный код.
import React, { Component } from "react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Modal from "@mui/material/Modal";
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4
};
class Contact extends Component {
constructor(props) {
super(props);
this.state = {
open: false
};
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
}
static displayName = Contact.name;
handleOpen() {
this.setState({ open: true });
}
handleClose() {
this.setState({ open: false });
}
render() {
return (
<div>
<div className="center">
<Button onClick={this.handleOpen}>Contact us</Button>
</div>
<Modal
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Contact us
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Contact us at hello @ mycompany.com
</Typography>
</Box>
</Modal>
</div>
);
}
}
export default Contact;
Ответ №2:
Вы ошиблись между работой с классами и крючками. Поскольку вы используете классы и setState
, вы должны установить состояние переменной open
, которая определяет, открыт ли модал или нет (это логическое значение).
Свойство open
модального компонента пользовательского интерфейса Material ожидает логическое значение, которое определяет, должен ли модал находиться в открытом состоянии или нет. Вы передаете свою государственную собственность open
в open
собственность, и это нормально. Но вам нужно обновлять его, setState
когда это необходимо.
Итак, вместо this.setState({ setOpen: true });
и this.setState({ setOpen: false });
Вы должны использовать this.setState({ open: true });
и this.setState({ open: false });
.
Государственная собственность setOpen
в этом случае не нужна. Это фиксированный код:
import React, { Component } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Modal from '@mui/material/Modal';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4
};
export class Contact extends Component {
constructor(props) {
super(props);
this.state = {
open: false
}
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
}
static displayName = Contact.name;
handleOpen() { this.setState({ open: true }); }
handleClose() { this.setState({ open: false }); }
render() {
return(
<div>
<div className="center">
<Button onClick={() => this.handleOpen()}>Contact us</Button>
</div>
<Modal open={this.state.open} onClose={()=> this.handleClose()}
aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description">
<Box sx={style}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Contact us
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Contact us at hello @ mycompany.com
</Typography>
</Box>
</Modal>
</div >
);
}
}
Комментарии:
1. Также
<Modal open={() => this.state.open()}
должно быть<Modal open={this.state.open}
, не так ли ?2. ДА. Вы правы, я отредактирую его