反应-呈现动态内容的正确方法吗?

时间:2019-04-27 11:21:35

标签: reactjs state 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 有什么合适的方法可以将动态内容呈现给父对象?

1 个答案:

答案 0 :(得分:1)

当将Modal做成简单的可重用Modal组件时,我不确定为什么需要创建父child组件。

有关如何实现控制子模式的有状态父的详细说明,请参见here


但是,如果您必须有一个父级Modal组件,则可以创建一个render prop来传递props,以供其children使用。

工作示例

Edit Parent Modal

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中的isOpenonCloseModalonOpenModal-您会注意到,这种方法有重复的parent逻辑。虽然这种方法可以完全控制父级,但它是重复性的。但是,您可以通过将“打开模态”按钮逻辑移到父级,并传入isOpen这样的道具以使其更加灵活,,您仍然会失去对<Modal btnTitle="Open Modal">为{{1}时最初呈现的内容的控制}。)

isOpen