Я взял модальный компонент из response-semanti c -ui и настроил его на диалог подтверждения или предупреждения или на традиционный модал.
Однако я сталкиваюсь с проблемой, когда модал, который используется для обратной связи на странице профиля при загрузке изображения в качестве аватара, также запускается при выходе из панели меню / навигации.
=======================================
home | *profile | dashboard | logout /* You are supposed to get a Modal to confirm your desire to log out */
=======================================
-------------
| choose file | /* And this should trigger a Modal to confirm with a success OR failure!!
-------------
Это мой модальный компонент:
import React, { PureComponent, Component } from 'react'
import { Button, Modal } from 'semantic-ui-react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { logOutUser } from '../../store/reducers/users/index'
import { modalStateOn, modalStateOff } from '../../store/reducers/ui/index'
class MyModal extends PureComponent {
constructor(props) {
super(props);
this.state = {
isAlertModal: this.props.isAlertModal
}
}
componentDidMount() {
const { isAlertModal } = this.props;
this.setState({ isAlertModal: isAlertModal})
}
static getDerivedStateFromProps(props, state) {
if (props.isAlertModal !== state.isAlertModal) {
return {
isAlertModal: props.isAlertModal,
};
}
// Return null if the state hasn't changed
return null;
}
// componentDidUpdate(prevProps, prevState) {
// if (this.props.isAlertModal !== prevProps.isAlertModal) {
// this.setState({ isAlertModal: this.props.isAlertModal })
// }
// }
close = () => {
const { modalStateOff } = this.props
modalStateOff();
}
logOutUser = () => {
const { logOutUser } = this.props
logOutUser()
}
render() {
const { modalActive } = this.props
return (
<>
<Modal dimmer={'blurring'} centered={true} size={'mini'} open={modalActive} onClose={this.close}>
<Modal.Header>
<p>{this.props.message}</p>
</Modal.Header>
<Modal.Actions>
{this.state.isAlertModal ?
<Button
color='black'
onClick={()=> {this.close()}}
content={this.props.affirmativeUsed}
/>
:
<>
<Button
color='black'
onClick={this.close}
>
No
</Button>
<Button
positive
icon='checkmark'
labelPosition='right'
content={this.props.affirmativeUsed}
onClick={() => { this.close(); this.logOutUser() }}
/>
</>
}
</Modal.Actions>
</Modal>
</>
)
}
}
MyModal.propTypes = {
message: PropTypes.string,
affirmativeUsed: PropTypes.string
}
function mapStateToProps(state) {
const { ui } = state
const { modalActive } = ui
return { modalActive }
}
const mapDispatchToProps = dispatch =>
bindActionCreators({ logOutUser, modalStateOn, modalStateOff }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(MyModal)
Как вы можете видеть, я использую getDerivedStateFromProps
и componentDidMount
и задаю локальное состояние из избыточного состояния в качестве решения. .
Что также странно В компоненте Profile у меня есть пропеллер, используемый в качестве триггера для показа модального окна, который не имеет ничего общего с навигационным, но он все еще пузырится!
import React, { PureComponent } from 'react';
import './ImageUploader.css';
import ImageModal from '../Modal/MyModal.jsx'
import axios from 'axios';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { loadAvatar } from '../../store/reducers/users/index'
import { modalStateOn, modalStateOff } from '../../store/reducers/ui/index'
class ImageUploader extends PureComponent {
constructor(props) {
super(props);
this.uploadImage = this.uploadImage.bind(this);
}
// componentDidUpdate(previousProps, previousState) {
// console.log("this.props.userAvatar in componentDidUpdate in ImageUploader", this.props.userAvatar)
// if (previousProps.userAvatar !== this.props.userAvatar) {
// console.log("this.props.userAvatar in componentDidUpdate", this.props.userAvatar);
// loadAvatarImage(this.props.userAvatar)
// }
// }
setDefaultImage(){
var defaultImage = '../../static/profile-avatars/assets/default-img.jpg';
this.loadAvatarImage(defaultImage)
}
loadAvatarImage(img) {
var { loadAvatar } = this.props;
loadAvatar(img)
}
uploadImage(e, method) {
const { modalStateOn } = this.props
if (method === "multer") {
let imageFormObj = new FormData();
imageFormObj.append("imageName", "multer-image-" + Date.now());
imageFormObj.append("imageData", e.target.files[0]);
this.loadAvatarImage(window.URL.createObjectURL(e.target.files[0]))
var config = { headers: { 'content-type': 'multipart/form-data' }}
axios.post(`http://localhost:8016/images/uploadmulter`, imageFormObj, config )
.then((data) => {
if (data.data.success) {
console.log("data ", data);
modalStateOn();
console.log('this.props in ImageUploader uploadImageFunction', this.props)
}
})
.catch((err) => {
alert("Error while uploading image using multer");
this.setDefaultImage();
});
}
}
render() {
var { userAvatar, modalActive } = this.props;
return (
<>
<div className="main-container">
<h3 className="main-heading">Image Upload App</h3>
<div className="image-container">
<div className="process">
<h4 className="process__heading">Process: Using Multer</h4>
<p className="process__details">Upload image to a node server, connected to a MongoDB database, with the help of multer</p>
<form action="/uploadmulter" method="post" encType="multipart/form-data" >
<input type="file" name="avatar" className="process__upload-btn"
onChange={(e) => {
this.uploadImage(e, "multer");
}} />
<img src={userAvatar} alt="upload-image" className="process__image" />
</form>
</div>
</div>
</div>
{(userAvatar) && <ImageModal
key={userAvatar}
isAlertModal={true}
affirmativeUsed="OK!"
message="Your image has been uploaded succesfully"
/>}
</>
);
}
}
function mapStateToProps(state) {
const { ui, users } = state
const { userAvatar } = users
const { modalActive } = ui
return { userAvatar, modalActive }
}
const mapDispatchToProps = dispatch =>
bindActionCreators({ loadAvatar, modalStateOn, modalStateOff }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(ImageUploader)