[英]Proper way to build bootstrap modals and notifications in React JS?
I would like to have modals and notifications in my app and coming from using old jQuery Bootstrap, creating modals and notifications were really easy but now I am pretty confused on how to implement this in the virtual DOM using the react component system.我想在我的应用程序中有模态和通知,并且来自使用旧的 jQuery Bootstrap,创建模态和通知真的很容易,但现在我对如何使用 react 组件系统在虚拟 DOM 中实现这一点感到非常困惑。
This is what I believe the standard react way to build modals in React within a component:这就是我认为在组件内在 React 中构建模态的标准反应方式:
Index/Router Component >
Main Layout Component >
{...Page Components... }
{...Child Component}
{<Modal /> or <Notification />}
The issue with this is I dont want to constantly have to import and create a <Modal>
or <Notification />
component within my sub components, instead maybe just call a utility function such as {app.notify({type: 'success', message: 'some message'})}
or app.modal({...customconfig})
and have both defined within my Main layout component
which get triggerd through any child components.问题是我不想经常在我的子组件中导入和创建
<Modal>
或<Notification />
组件,而可能只是调用一个实用函数,例如{app.notify({type: 'success', message: 'some message'})}
或app.modal({...customconfig})
并且都在我的Main layout component
定义,这些Main layout component
通过任何子组件触发。
Any help on this would be great, thanks!对此的任何帮助都会很棒,谢谢!
You do not need to keep your Modal
component in a hierarchy.您不需要将
Modal
组件保持在层次结构中。 Your Modal
component should be an independent component which would take appropriate props
to decide what needs to be displayed.你的
Modal
组件应该是一个独立的组件,它会采用适当的props
来决定需要显示什么。 Eg例如
<Modal message={"This is my modal"} showOkCancel={true} showYesNo={false} handleOkYes={()=>console.log("OK clicked")} handleCancelNo={()=>console.log("Cancel clicked"} />
In the above example, the Modal
accepts a number of props which would help it decide the message to display, the buttons to display and the actions that need to take on said button click.在上面的例子中,
Modal
接受许多道具,这些道具将帮助它决定要显示的消息、要显示的按钮以及在所述按钮点击时需要采取的操作。
This kind of a component can reside outside your component hierarchy and can be imported into any component that needs to show a modal.这种组件可以驻留在组件层次结构之外,并且可以导入到任何需要显示模态的组件中。 The parent component would just need to pass the appropriate props to show the modal.
父组件只需要传递适当的道具来显示模态。
Hope this helps.希望这可以帮助。
So here is the approach I took to resolve this.所以这是我用来解决这个问题的方法。
First here is how you want to structure the modal and notification components:首先是您希望如何构建模态和通知组件:
{Index/Router Component}
{Main Layout Component <Modal /> or <Notification />}
{...Page Components... }
{...Child Component calls app.modal({...config}) or app.notify(...config)}
For notifications, I used a plugin called react-notification-system and for modal, I just wrote it myself.对于通知,我使用了一个名为react-notification-system的插件,对于模态,我只是自己编写的。
Here is my code:这是我的代码:
Layout.js布局.js
import React from "react";
import {Link} from 'react-router';
import NotificationSystem from 'react-notification-system';
import AppHeader from "#/ui/header/AppHeader";
import AppFooter from "#/ui/footer/AppFooter";
import Modal from "#/ui/modals/modal/Modal";
import "@/main.scss";
import './layout.scss';
export default class Layout extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
app.notify.clear = this.refs.notificationSystem.clearNotifications;
app.notify = this.refs.notificationSystem.addNotification;
app.modal = this.refs.modal.updateProps;
}
render() {
return (
<div class="app">
<div class="header">
<AppHeader page={this.props.location.pathname.replace('/', '')}/>
</div>
<div class="body">
{this.props.children}
</div>
<div class="footer">
<AppFooter />
</div>
<NotificationSystem ref="notificationSystem" style={false} />
<Modal ref="modal" />
</div>
);
};
}
Modal.js Modal.js
import React from "react";
import ReactDOM from 'react-dom';
import SVGInline from "react-svg-inline";
import {closeSvg} from '#/utils/Svg';
export default class Modal extends React.Component {
constructor(props) {
super(props);
this.state = {
showHeader: true,
showFooter: false,
title: "",
size: '',
className: '',
id: '',
footerContent: null,
showSubmitBtn: true,
showCancelBtn: true,
cancelBtnText: "Cancel",
successBtnText: "Save Changes",
onModalClose: () => {},
showModal: false,
html: () => {}
}
this.updateProps = this.updateProps.bind(this);
this.hideModal = this.hideModal.bind(this);
}
componentWillMount() {
var self = this;
var $modal = $(ReactDOM.findDOMNode(this));
}
componentDidUpdate(prevProps, prevState) {
if(this.state.showModal) {
$('body').addClass('modal-open');
} else {
$('body').removeClass('modal-open');
}
}
componentWillUnmount() {
// $('body').removeClass("modal-open");
}
componentWillReceiveProps(nextProps) {
console.log(nextProps);
}
updateProps(args) {
let merged = {...this.state, ...args};
this.setState(merged);
}
hideModal() {
this.setState({
showModal: false
});
this.state.onModalClose();
}
buildFooter() {
if(this.props.footerContent) {
return (
<div class="content">
{this.props.footerContent}
</div>
)
} else if(this.props.showCancelBtn && this.props.showSubmitBtn) {
return (
<div class="buttons">
<button type="button" class="btn btn-default" data-dismiss="modal" onClick={this.props.onModalClose}>{this.props.cancelBtnText}</button>
<button type="button" class="btn btn-success">{this.props.successBtnText}</button>
</div>
);
} else if(this.props.showCancelBtn) {
return (<button type="button" class="btn btn-default" data-dismiss="modal" onClick={this.props.onModalClose}>Close</button>);
} else if(this.props.showSubmitBtn) {
return (<button type="button" class="btn btn-success">Save changes</button>);
}
}
render() {
let {
id,
className,
onModalClose,
size,
showHeader,
title,
children,
showFooter,
showModal,
html
} = this.state;
return (
<div class={`modal-wrapper`} >
{
showModal ?
<div class={`modal fade in ${className}`} role="dialog">
<div class="bg" ></div>
<div class={`modal-dialog ${size}`}>
<div class="modal-content">
{ showHeader ?
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<SVGInline svg={closeSvg} />
</button>
<h4 class="modal-title">{ title }</h4>
</div> : '' }
<div class="modal-body" >
{html()}
</div>
{ showFooter ?
<div class="modal-footer">
{ this.buildFooter() }
</div> : ''
}
</div>
</div>
</div>
: ''
}
</div>
);
}
}
then in any of your child components you can just call within your render function:然后在您的任何子组件中,您都可以在渲染函数中调用:
app.notify({
message: message,
level: 'error'
});
or或者
app.modal({
showModal: true,
className: "fullscreen-image-modal",
size: "modal-lg",
html: () => {
return (<img src={listingManager.LISTINGS_PATH + imgUrl} />);
}
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.