简体   繁体   English

ReactJS:维护父子之间的数据状态

[英]ReactJS: Maintain data state between parent and child

There's a parent, <MessageBox /> element, which contains a list of messages stored in its state . 有一个<MessageBox />父元素,其中包含以state形式存储的messages列表。 For each message in messages , a <Message /> element is created inside <MessageBox /> which has fields for message.subject and message.body . 对于每一个messagemessages ,一个<Message />被内部产生元件<MessageBox />具有用于字段message.subjectmessage.body A user can edit the message.subject and message.body and once done, the message object is sent back to <MessageBox /> through a props.updateHandler() to maintain the message state in the parent. 用户可以编辑message.subjectmessage.body ,一旦完成,则通过props.updateHandler()message对象发送回<MessageBox /> ,以保持父对象中的消息状态。

In my current approach, I'm storing the message data in MessageBox 's state and in the render() function, I'm creating the <Message /> elements and passing a callback to each of them to send back data changes. 在当前方法中,我将消息数据存储在MessageBox的状态中,并在render()函数中,创建<Message />元素,并将回调传递给每个元素以发送回数据更改。 In the callback, the updated data from each of the <Message /> elements is updated back into MessageBox 's state. 在回调中,来自每个<Message />元素的更新数据将更新回MessageBox的状态。 The reason for this is to keep all the recent updated data in one place only. 这样做的原因是将所有最近更新的数据仅保留在一个位置。 The above approach creates havoc if shouldComponentUpdate() method in <Message /> is not overloaded (infinite recursion). 如果<Message /> shouldComponentUpdate()方法未过载(无限递归),则上述方法会造成严重破坏。

Is there a better approach for this? 有更好的方法吗? I've to write a lot of code just to override the builtin methods to keep the entire thing stable. 我必须编写大量代码以覆盖内置方法,以使整个过程保持稳定。 As I'm not planning to go for Flux/Redux, is there a React-only approach for this? 由于我不打算使用Flux / Redux,是否有只使用React的方法?

EDIT: Since there's a lot of confusion, I'm adding minimal code. 编辑:由于存在很多混乱,我添加了最少的代码。

class Message extends React.Component {
    constructor(props) {
        this.state = {
            subject: this.props.subject,
            body: this.props.body,
            type: this.props.type,
            messageIndex: this.props.messageIndex
        };
    }

    componentDidUpdate() {
        this.props.updateHandler(messageIndex, {
            subject: this.state.subject,
            body: this.state.body,
            type: this.state.type
        });
    }

    render() {
        return (
            <div>
                <input
                    type="text"
                    defaultValue={this.state.subject}
                    onBlur={e => this.setState({subject: e.target.value})} />

                <input
                    type="text"
                    defaultValue={this.state.subject}
                    onBlur={e => this.setState({body: e.target.value})} />

                <select
                    type="text"
                    value={this.state.subject}
                    onChange={e => this.setState({type: e.target.value})}>
                    <option>Type 1</option>
                    <option>Type 2</option>
                </select>
            </div>
        )
    }
}

class MessageBox extends React.Component {
    constructor(props) {
        this.state = {
            messages: aListOfMessageObjects
        }
    }

    updateHandler(message) {
        // Message update happens here and returns a list updatedMessages
        this.setState({
            messages: updatedMessages
        });
    }

    render() {
        let _this = this;

        var messagesDOM = this.state.messages.map((m) => {
            return (
                <Message
                    message={m}
                    updateHandler={_this.updateHandler.bind(_this)} />
            );
        })

        return (
            <div>
                {messagesDOM}
            </div>
        );
    }
}

If that can help, read thinking-in-react . 如果有帮助,请阅读“行动中思考” It explains how data should go only one way to avoid be lost in UI updates. 它解释了数据应该如何只不过是避免在UI更新中丢失的一种方式。

React ToDo MVC will provide you an example of React good practice on a real case React ToDo MVC将为您提供实际案例中的React最佳实践示例

To know how to pass props from your parent to children read controlled-components . 要知道如何将道具从父母那里传递给孩子,请阅读受控组件 you'll have to use value and onBlur on each input. 您必须在每个输入上使用valueonBlur Any onBlur event will call this.props.updateHandler with e as parameter instead of e => this.setState({type: e.target.value}) . 任何onBlur事件都将使用e作为参数而不是e => this.setState({type: e.target.value})来调用this.props.updateHandler

  1. Don't do a callback to MessageBox from componentDidUpdate() of Message . 不要从Message componentDidUpdate()MessageBox进行回调。 Do a callback directly from an action in Message. 直接从Message中的操作进行回调。
  2. You don't need state in Message component at all. 您根本不需要Message组件中的状态。 Props will keep the values you are interested if you update parent's state properly. 如果您正确更新父母的状态,则道具将保留您感兴趣的值。

What you need is something like: 您需要的是这样的:

    <input type="text"
       defaultValue={this.props.subject}
       onBlur={e => this.updateSubject(e.target.value)} />

    updateSubject: function(newSubjectValue) {
         this.props.updateHandler(messageIndex, {
            subject: newSubjectValue,
            body: this.props.body,
            type: this.props.type
    });
    }

That way the component will get re-rendered, but won't do another call to the parent's setState. 这样,组件将被重新渲染,但不会再调用父对象的setState。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM