【问题标题】:How to setState of parent components in React如何在 React 中设置父组件的状态
【发布时间】:2016-01-08 09:46:38
【问题描述】:

在我的例子中,TopicList 是父组件,IndividualTopic 是子组件。当用户单击子组件时,它会将 showTopicDescription 的状态更改为 true。但是,如何将 showTopicDescription 的值传递给父组件(TopicList)或直接设置父组件状态?

var TopicsList = React.createClass({

    render: function () {
        return (
            <div className="row">
                <IndividualTopic topic_no="1">
                    Topic 1
                </IndividualTopic>
                <IndividualTopic topic_no="2">
                    Topic 2
                </IndividualTopic>
                <IndividualTopic topic_no="3">
                    Topic 3
                </IndividualTopic>
                <IndividualTopic topic_no="4">
                    Topic 4
                </IndividualTopic>
                <div className="col-sm-12">
                    { this.state.showTopicDescription ? <IndividualTopicPages /> : null }
                </div>
            </div>
        );
    }
});

var selected_topic_no;

var IndividualTopic = React.createClass({
    getInitialState: function() {
        return { showTopicDescription: false };
    },
    onClick: function() {
        this.setState({ showTopicDescription: true });
        selected_topic_no = this.props.topic_no - 1;
    },
    render: function () {
        return (
            <div>
                <div className="col-sm-2">
                    <div onClick={this.onClick} className="single-topic" data-topic-no={this.props.topic_no}>
                        {this.props.children}
                    </div>
                </div>
            </div>
        );
    }

});

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

从IndividualTopic的click handler中调用父组件的setTopicDescription函数,使用我们在父组件的render方法中注册的this.props。参考下面的代码-

var TopicsList = React.createClass({
    setTopicDescription: function(topicDescription){
     //HERE WE GET THE TOPIC DESCRIPTION FLAG. CHEEERS WE CAN DO WHAT WE NEED OVER HERE  
    },
    render: function () {
        return (
            <div className="row">
                <IndividualTopic topic_no="1" setTopicDescription={this.setTopicDescription} >
                    Topic 1
                </IndividualTopic>
                <IndividualTopic topic_no="2" setTopicDescription={this.setTopicDescription}>
                    Topic 2
                </IndividualTopic>
                <IndividualTopic topic_no="3" setTopicDescription={this.setTopicDescription}>
                    Topic 3
                </IndividualTopic>
                <IndividualTopic topic_no="4" setTopicDescription={this.setTopicDescription}>
                    Topic 4
                </IndividualTopic>
                <div className="col-sm-12">
                    { this.state.showTopicDescription ? <IndividualTopicPages /> : null }
                </div>
            </div>
        );
    }
});

var selected_topic_no;

var IndividualTopic = React.createClass({
    getInitialState: function() {
        return { showTopicDescription: false };
    },
    onClick: function() {
        this.setState({ showTopicDescription: true });
        selected_topic_no = this.props.topic_no - 1;
        this.props.setTopicDescription({ showTopicDescription: true }); 
    },
    render: function () {
        return (
            <div>
                <div className="col-sm-2">
                    <div onClick={this.onClick} className="single-topic" data-topic-no={this.props.topic_no}>
                        {this.props.children}
                    </div>
                </div>
            </div>
        );
    }

});

【讨论】:

  • 我收到一个错误“未捕获的 ReferenceError: setTopicDescription is not defined”
  • 如果你的目标是纯粹的封装,你可能会争辩说 IndividualTopic 应该只传递一个回调函数作为来自 TopicsList 的道具。然后 selected_topic_no 和 showTopicDescription 应该绑定到 IndividualTopic 中的道具。
  • @jolyonruss 如果您能举个例子,将不胜感激。
【解决方案2】:

这是基于我的评论的评论版本。

我已经添加了一堆 cmets,请随时提出更多问题,我试图表达的主要观点是 IndividualTopic 组件应该是愚蠢的,并且里面几乎没有逻辑,只需通过 props 和调用回调。

这是完全未经测试的伪代码,请不要期望它按原样工作 - 我只是想说明一种方法。

var TopicsList = React.createClass({

    // setup our generic callback method to handle all topic selection
    // this gets passed the event object and topic ID and sets the state
    topicSelectionCallback: function(topicID, event) {
        this.setState({
            showTopicDescriptions: true,
            selectedTopicID: topicID
        });
    },

    // maybe you need to close the topic as well...
    closeTopicCallback() {
        this.setState({
            showTopicDescription: false
        });
    }

    render: function () {
        return (
            <div className="row">
                // I've neatened up your syntax for the IndividualTopic elements
                // props should be camel case and one their own line, I pass
                // through the callback as well as the label
                <IndividualTopic 
                    topicID="1" 
                    selectionCallback={this.topicSelectionCallback} 
                    label="Topic"
                >
                <IndividualTopic 
                    topicID="2" 
                    selectionCallback={this.topicSelectionCallback} 
                    label="Topic"
                >
                <IndividualTopic 
                    topicID="3" 
                    selectionCallback={this.topicSelectionCallback} 
                    label="Topic"
                >
                <IndividualTopic 
                    topicID="4" 
                    selectionCallback={this.topicSelectionCallback} 
                    label="Topic"
                >
                <div className="col-sm-12">
                    { this.state.showTopicDescription ? 
                        // pass the selected topic ID assuming this component will
                        // then re-render based on the ID that it's passed
                        <IndividualTopicPages 
                            selectedTopic={this.state.selectedTopicID}
                            closeTopicCallback={this.closeTopicCallback} // closing the topic
                        /> 
                    : null }
                </div>
            </div>
        );
    }
});

// this doesn't really need to be a var in this scope
// var selected_topic_no;

var IndividualTopic = React.createClass({
    onClick: function(event) {
        // assuming you're using ES6, declare this as a let as it's only
        // ever used here, if not just a local var will work fine
        let selectedTopicID = this.props.topicID - 1;
        // call the callback that's passes as a prop, send the topic ID
        // as a parameter
        this.props.topicSelectionCallback(event, selectedTopicID);
    },

    render: function () {
        return (
            <div>
                <div className="col-sm-2">
                    <div onClick={this.onClick} className="single-topic" data-topic-id={this.props.topicID}>
                        {this.props.label} {this.props.topicID} // render out the label and topicID here
                    </div>
                </div>
            </div>
        );
    }
});

【讨论】:

  • 我收到这个错误“Uncaught TypeError: this.props.topicSelectionCallback is not a function”
  • 这可以是任意数量的东西。错误在哪里抛出?在 IndividualTopic 或 TopicsList 中?如果您在 CodePen 上发布您的代码,我们可以尝试找出问题的根源。
猜你喜欢
  • 2020-12-14
  • 2020-10-06
  • 1970-01-01
  • 2019-09-07
  • 2021-03-21
  • 2018-01-02
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
相关资源
最近更新 更多