我想基于https://github.com/reactjs/react-modal
为对话框窗口创建组件API我想渲染反应组件与renderDOM,获取组件实例并调用模态API,它的意思是例如open(),close()等。
因此,更确切地说,我想使用当前的组件状态(如API工程),而不是使用道具。
我有所有模态的简单基类:
export class BaseModal extends Modal {
constructor() {
super();
this.state = BaseModal._getInitState();
}
static get style() {
return {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)'
}
};
}
open() {
this.setState({isOpen: true});
}
close() {
this.setState({isOpen: false});
}
render() {
return this.state.isOpen ? (
<div className="modal modal__{this.name}">
<Modal isOpen={this.state.isOpen}
onRequestClose={this.close}
style={BaseModal.style}
contentLabel={this.getHeaderContent()}
parentSelector={BaseModal._getParentSelector}>
<button onClick={this.close}>X</button>
<div className="modal__body">
{this.getBodyContent()}
</div>
<div className="modal__footer">
{this.getFooterContent()}
</div>
</Modal>
</div>
) : null;
}
getHeaderContent() {
throw new Error("Not implement in child class.");
}
getBodyContent() {
throw new Error("Not implement in child class.");
}
getFooterContent() {
throw new Error("Not implement in child class.");
}
static _getInitState() {
let state = {};
state.isOpen = false;
}
}
现在我有了子组件:
export class RecommendTripModal extends BaseModal {
getHeaderContent() {
return "Test modal dialog";
}
getBodyContent() {
return <p>Test modal body</p>;
}
getFooterContent() {
return <p>Test modal footer</p>;
}
}
好的,这很好,但现在我想打电话给这样的话:
let recommendedTripModal = ReactDOM.render(React.createElement(RecommendTripModal, null), document.querySelector("#modals"));
//open dialog
recommendedTripModal.open();
但现在是上下文的问题。因为this.state.isOpen
具有RecommendTripModal上下文且状态为null。有没有办法,怎么解决这个问题的反应?这是坚实的方式吗?或者我应该以不同的方式创建所需的API?
感谢您的时间!
答案 0 :(得分:1)
好的,让我们在这里深入挖掘,最好的方法是使用React上下文和HoC魔法力量
的 Modal.js 强>
import React from "react";
import PropTypes from "prop-types";
import { omit } from "lodash";
export class Modal extends React.Component {
static contextTypes = {
modalOpen: PropTypes.bool
};
static propTypes = {
children: PropTypes.node
};
render() {
if (!this.context.modalOpen) return null;
return (
<div>
<h1>I am base modal title</h1>
<div>{this.props.children}</div>
</div>
);
}
}
export class ModalContext extends React.Component {
static childContextTypes = {
modalOpen: PropTypes.bool
};
static defaultProps = {
onOpen: () => {},
onClose: () => {}
};
static propTypes = {
children: PropTypes.func.isRequired
};
constructor(...args) {
super(...args);
this.handleOpen = this.handleOpen.bind(this);
this.handleClose = this.handleClose.bind(this);
}
state = {
isOpen: false
};
getChildContext() {
return {
modalOpen: this.state.isOpen
};
}
handleClose() {
if (this.state.isOpen) {
this.setState({ isOpen: false });
}
}
handleOpen() {
if (!this.state.isOpen) {
this.setState({ isOpen: true });
}
}
render() {
const { identity, children } = this.props;
return children({
[identity]: {
open: this.handleOpen,
close: this.handleClose,
isOpen: this.state.isOpen
}
});
}
}
export default function modal(initialModalProps = {}) {
return function(Component) {
const componentName =
Component.displayName || Component.name || "Component";
return class extends React.Component {
static displayName = `Modal(${componentName})`;
static propTypes = {
identity: PropTypes.string
};
static defaultProps = {
identity: "modal"
};
render() {
const { identity } = this.props;
return (
<ModalContext
identity={identity}
{...initialModalProps}
{...this.props[identity]}
>
{modalProps => (
<Component
{...omit(this.props, identity, "identity")}
{...modalProps}
/>
)}
</ModalContext>
);
}
};
};
}
<强> HelloWorldModal.js 强>
import React from "react";
import withModal, { Modal } from "./modal";
class HelloWorldModal extends React.Component {
render() {
const { modal } = this.props;
return (
<div>
<button type="button" onClick={modal.open}>
Open Modal
</button>
<button type="button" onClick={modal.close}>
Close Modal
</button>
<Modal>Yeah! I am sample modal!</Modal>
</div>
);
}
}
export default withModal()(HelloWorldModal);
如果你很懒,我准备了一个带有工作代码的codeandbox:)
https://codesandbox.io/s/2oxx2j4270?module=%2Fsrc%2FHelloWorldModal.js