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

Storing React.js state in component owner

我有我的组件所有者:

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 模块,那么我应该能够初始化它,然后保存它自己的数据?

我还能如何处理 this/tidy 这件事?

除了我上面的评论。 如果您的全局消息状态仅由您的 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 向组件提供信息来使用一个组件来显示不同的错误。