在组件所有者中存储React.js状态

时间:2015-05-11 11:52:21

标签: javascript backbone.js reactjs

我有我的组件所有者:

var React = require('react');
var Backbone = require('backbone');

var GlobalMessage = require('./shared/global-message.jsx');

module.exports = React.createClass({

    getInitialState: function() {
        return {
            global_message: {
                message: 'error',
                type: ''
            }
        };
    },

    componentWillMount: function() {
        Backbone.on('global-message', function(data) {
            this.setState({
                global_message: data
            });
        }.bind(this));
    },

    render: function() {
        return (
            <div>
                <GlobalMessage message={this.state.global_message.message} type={this.state.global_message.type} />
            </div>
        );
    }
});

我的global-message.jsx

var React = require('react/addons');

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

module.exports = React.createClass({
    render: function() {
        return (
            <div className='global-message-wrap'>
                <ReactCSSTransitionGroup transitionName='global-message'>
                    <p className='global-message-text' key={this.props.message}>{this.props.message}</p>
                </ReactCSSTransitionGroup>
            </div>
        );
    }
});

这一切都运行正常,当我trigger我的Backbone事件时,所有内容都更新。

但是。

如果这是React Way™,那么就这样吧,但对我而言,存储在父母中的组件的状态感觉不自然。对我来说,如果我有一个global-message模块,那么我应该能够初始化它,然后保存自己的数据吗?

我怎么能接近这个/整理一下?

1 个答案:

答案 0 :(得分:1)

除了上面的评论。 如果您的全局消息状态仅由global-message.jsx组件使用,则可以将所有订阅逻辑移动到此组件:

var React = require('react/addons');

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

module.exports = React.createClass({
    getInitialState: function() {
        return {
            message: 'error',
            type: ''
        };
    },
    componentWillMount: function() {
        Backbone.on('global-message', function(data) {
            this.setState(data);
        }.bind(this));
    },        
    render: function() {
        if (!this.state.type) {
            return null;
        }
        return (
            <div className='global-message-wrap'>
                <ReactCSSTransitionGroup transitionName='global-message'>
                    <p className='global-message-text' key={this.state.message}>{this.state.message}</p>
                </ReactCSSTransitionGroup>
            </div>
        );
    }
});

你可以在任何地方使用你的组件而不用任何道具:

var React = require('react');
var Backbone = require('backbone');

var GlobalMessage = require('./shared/global-message.jsx');
module.exports = React.createClass({
    render: function() {
        return (
            <GlobalMessage />
        );
    }
});

但是如果组件的某些子节点之间共享某个状态,最好将状态存储在其父组件中,如下所示:

var UserInfoComponent = React.createClass({
    getInitialState: function () {
        return api.getCurrentUser(); // {firstname: 'John', lastname: 'Smith', avatar: 'http://...'}
    },
    componentDidMount: function () {
        // subscribe logic here
    },
    componentWillUnmount: function () {
        // unsubscribe logic here
    }
    render: function () {
        return (
            <div>
                <UserAvatarComponent avatar={this.state.avatar} />
                <UserMenuComponent user={this.state} />
            </div>
        );
    }
});

使用父组件作为数据提供者的其他变体:例如,您有ErrorMessageComponent,它封装了一些用于显示某些错误消息的代码。因此,最好通过避免在组件内部获取数据来保持此组件的清洁和可重用性,并为其父级保留此逻辑。因此,在不同的情况下,您可以使用一个组件通过使用props向组件提供信息来显示不同的错误。