我想通过向其注入组件来使模态视图具有动态内容。
class RootView extends Component {
state = {
modalBody: null
}
setModalBody = (body) => {
this.setState({modalBody: body})
}
render() {
return(<ContextProvider value={this.setModalBody}><Modal>{this.state.modalBody}</Modal></ContextProvider>)
}
}
然后在所有子视图中,我使用setState
更改父项modalBody
可以在每个路线上设置modalBody
,这意味着modalBody
可以是input
列表,selection
列表或仅文本。因此modalBody
必须具有其状态才能控制这些输入。
通过这种方式,它可以正常显示,但是状态更改后无法更新动态内容。父级的动态内容无法收到ChildView的新状态,重新渲染后,我不得不setModalBody
一遍又一遍。
例如,如果modalBody中的输入已更改,则无法更新父项。
class ChildView extends Component {
state = {
inputValue: null
}
handleChange = (e) => {
this.setState({inputValue: e.target.value})
}
setModalBody(body) {
this.props.context.setModalBody(<input value={this.state.inputValue} onChange={this.handleChange} />)
}
render() {
return(<Modal>{this.state.modalBody}</Modal>)
}
}
完整代码:https://codesandbox.io/s/lp5p20mx1m 有什么合适的方法可以将动态内容呈现给父对象?
答案 0 :(得分:1)
当将Modal
做成简单的可重用Modal
组件时,我不确定为什么需要创建父child
组件。
有关如何实现控制子模式的有状态父的详细说明,请参见here。
但是,如果您必须有一个父级Modal
组件,则可以创建一个render prop
来传递props
,以供其children
使用。
工作示例:
components / Modal.js (parent
组件-该组件具有许多较小的组件,这些组件为了便于重用和易于理解而进行了分离-它们基本上很简单{{1 }},并附加了div
-请参阅下面的注释)
styles
components / Example.js (import React, { Fragment, Component } from "react";
import PropTypes from "prop-types";
import BackgroundOverlay from "../BackgroundOverlay"; // grey background
import ClickHandler from "../ClickHandler"; // handles clicks outside of the modal
import Container from "../Container"; // contains the modal and background
import Content from "../Content"; // renders the "children" placed inside of <Modal>...</Modal>
import ModalContainer from "../ModalContainer"; // places the modal in the center of the page
class Modal extends Component {
state = { isOpen: false };
handleOpenModal = () => {
this.setState({ isOpen: true });
};
handleCloseModal = () => {
this.setState({ isOpen: false });
};
// this is a ternary operator (shorthand for "if/else" -- if cond ? then : else)
// below can be read like: if isOpen is true, then render the modal,
// else render whatever the child component is returning (in this case,
// initially returning an "Open Modal" button)
render = () =>
this.state.isOpen ? (
<Container>
<BackgroundOverlay />
<ModalContainer>
<ClickHandler
isOpen={this.state.isOpen}
closeModal={this.handleCloseModal}
>
<Content>
{this.props.children({
isOpen: this.state.isOpen,
onCloseModal: this.handleCloseModal,
onOpenModal: this.handleOpenModal
})}
</Content>
</ClickHandler>
</ModalContainer>
</Container>
) : (
<Fragment>
{this.props.children({
isOpen: this.state.isOpen,
onCloseModal: this.handleCloseModal,
onOpenModal: this.handleOpenModal
})}
</Fragment>
);
}
// these proptype declarations are to ensure that passed down props are
// consistent and are defined as expected
Modal.propTypes = {
children: PropTypes.func.isRequired // children must be a function
};
export default Modal;
组件接受child
中的isOpen
,onCloseModal
和onOpenModal
-您会注意到,这种方法有重复的parent
逻辑。虽然这种方法可以完全控制父级,但它是重复性的。但是,您可以通过将“打开模态”按钮逻辑移到父级,并传入isOpen
这样的道具以使其更加灵活,但,您仍然会失去对<Modal btnTitle="Open Modal">
为{{1}时最初呈现的内容的控制}。)
isOpen