React - 呈现动态内容的正确方法?
React - Proper way to render dynamic content?
我想通过向模态视图注入组件来使模态视图具有动态内容。
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
有什么正确的方法可以向父级呈现动态内容?
我不确定为什么您需要创建一个父 Modal
组件,而您可以使 Modal
成为一个简单的可重用 child
组件。
有关如何实现控制子模态的有状态父级的详细说明,请参见。
但是,如果您必须有一个父 Modal
组件,那么您可以创建一个 render prop
来传递 props
以供其 children
使用。
工作示例:
components/Modal.js(parent
组件——这有很多更小的组件,为了可重用性和易于理解而分开——它们基本上是简单的 div
附加了一些 styles
-- 见下面的注释)
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;
components/Example.js(child
组件从 parent
-- 使用这种方法,您会注意到,有重复的 isOpen
逻辑。虽然这种方法让您可以完全控制父级,但它是重复的。但是,您可以通过移动 isOpen
来简化组件=58=] 将按钮逻辑传递给父级,并传入 <Modal btnTitle="Open Modal">
之类的道具以使其更加灵活,但是 您仍然会失去对最初呈现的内容的一些控制当 isOpen
是 false
.)
import React, { Fragment } from "react";
import Modal from "../Modal";
import "./styles.css";
const Example = () => (
<div className="example">
<h2>Parent Modal Example</h2>
<Modal>
{({ isOpen, onCloseModal, onOpenModal }) =>
isOpen ? (
<Fragment>
<h1 className="title">Hello!</h1>
<p className="subtitle">There are two ways to close this modal</p>
<ul>
<li>Click outside of this modal in the grey overlay area.</li>
<li>Click the close button below.</li>
</ul>
<button
className="uk-button uk-button-danger uk-button-small"
onClick={onCloseModal}
>
Close
</button>
</Fragment>
) : (
<button
className="uk-button uk-button-primary uk-button-small"
onClick={onOpenModal}
>
Open Modal
</button>
)
}
</Modal>
</div>
);
export default Example;
我想通过向模态视图注入组件来使模态视图具有动态内容。
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 有什么正确的方法可以向父级呈现动态内容?
我不确定为什么您需要创建一个父 Modal
组件,而您可以使 Modal
成为一个简单的可重用 child
组件。
有关如何实现控制子模态的有状态父级的详细说明,请参见
但是,如果您必须有一个父 Modal
组件,那么您可以创建一个 render prop
来传递 props
以供其 children
使用。
工作示例:
components/Modal.js(parent
组件——这有很多更小的组件,为了可重用性和易于理解而分开——它们基本上是简单的 div
附加了一些 styles
-- 见下面的注释)
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;
components/Example.js(child
组件从 parent
-- 使用这种方法,您会注意到,有重复的 isOpen
逻辑。虽然这种方法让您可以完全控制父级,但它是重复的。但是,您可以通过移动 isOpen
来简化组件=58=] 将按钮逻辑传递给父级,并传入 <Modal btnTitle="Open Modal">
之类的道具以使其更加灵活,但是 您仍然会失去对最初呈现的内容的一些控制当 isOpen
是 false
.)
import React, { Fragment } from "react";
import Modal from "../Modal";
import "./styles.css";
const Example = () => (
<div className="example">
<h2>Parent Modal Example</h2>
<Modal>
{({ isOpen, onCloseModal, onOpenModal }) =>
isOpen ? (
<Fragment>
<h1 className="title">Hello!</h1>
<p className="subtitle">There are two ways to close this modal</p>
<ul>
<li>Click outside of this modal in the grey overlay area.</li>
<li>Click the close button below.</li>
</ul>
<button
className="uk-button uk-button-danger uk-button-small"
onClick={onCloseModal}
>
Close
</button>
</Fragment>
) : (
<button
className="uk-button uk-button-primary uk-button-small"
onClick={onOpenModal}
>
Open Modal
</button>
)
}
</Modal>
</div>
);
export default Example;