React + Flux:将初始状态变为商店

时间:2015-03-10 07:35:58

标签: javascript reactjs reactjs-flux refluxjs

我们最近从Angular切换到React + Flux来构建一个相当复杂的业务应用程序。

采用让一个容器组件将所有状态作为属性传递给组件树的方法不适合为我们开发应用程序,因为应用程序使用大型页面模式。足够的状态确实传递给模式,以便他们将数据加载到商店中。

我遇到的问题是我需要将一些初始状态(作为道具传递下来)放入模态组件的商店中。在this post,Facebook上的好人说,当同步不是目标时,可以使用道具作为初始状态。

这就是我当前进入商店的初始状态:

var ABC = React.createClass({
  ...  
  getInitialState: function() {
    return ABCStore.getInitialABCState(this.props.initialA);
  },
  ...

var ABCStore = Reflux.createStore({
  ...
  init: function() {
    _state = {
      a: null,
      b: 'B init',
      c: 'C init'
    };
  },

  getInitialABCState: function(initialA) {
    _state.a = initialA;
    return _state;
  },

  getABCState: function() {
    return _state;
  }
  ...

我不确定这样做的最佳做法是什么,或者这是否是Flux反模式?

3 个答案:

答案 0 :(得分:12)

使用getInitialState()更改商店状态对我来说感觉不对。你应该至少在componentWillMount中这样做。

我会在componentWillMount中触发一个动作并让商店处理程序更新商店的内部状态(这应该总是如此)。然后,您的组件的商店更改处理程序可以使用您当前称为"初始状态的任何数据"

答案 1 :(得分:4)

Reflux.listenTo在您提供第三个参数时执行此操作并且Reflux.connect mixin factory(在引擎盖下使用Reflux.listenTo)会自动为您处理此问题。这是一个例子:

var Actions = Reflux.createActions({"doIt"});

var Store = Reflux.createStore({
    listenables: [Actions],
    init: function() {
        this.state = "I like to";
    },
    onDoIt: function() {
        this.state = "Do it";
        this.trigger(this.state);
    },
    getInitialState: function() {
        return this.state;
    }
});

var DoItButton = React.createClass({
    mixins: [Reflux.connect(Store, "label")],
    onClick: function() {
        Actions.doIt();
    },
    render: function() {
        return (<div onClick={this.onClick}>{this.state.label}</div>);
    }
});

答案 2 :(得分:0)

像其他海报所说的那样,最好的办法就是在componentWillMount中触发一个动作。在ES6中,通常使用constructor

以下是有关如何使用ES6执行此操作的示例:

(请注意AuthorActions.initAuthors()依赖于实现,这只是一个示例。这可以从数据库获得初始状态。但最重要的是,此操作应该将具有初始状态的有效负载分派给调度程序)

var _authors = [];
var AuthorStoreInstance;

class AuthorStore extends EventEmitter {

    constructor(props) {
        super(props);
    }

    init() {
        AuthorActions.initAuthors();
        this.emitChange();
    }

    addChangeListener(cb) {
        this.on(CHANGE_EVENT, cb);
    }

    removeChangeListener(cb) {
        this.removeListener(CHANGE_EVENT, cb);
    }

    emitChange() {
        this.emit(CHANGE_EVENT);
    }

    getAllAuthors() {
        return _authors;
    }

    addAuthor(author) {
        _authors.push(author);
        this.emitChange();
    }

    setAuthors(authors) {
        _authors = authors;
    }

};


AuthorStoreInstance = new AuthorStore();

Dispatcher.register((action) => {
    switch(action.actionType) {
        case ActionTypes.CREATE_AUTHOR:
            AuthorStoreInstance.addAuthor(action.author);
            break;
        case ActionTypes.INITIALIZE:
            AuthorStoreInstance.setAuthors(action.initialData.authors);
            break;

        default:
            //do nothing
    }
});

AuthorStoreInstance.init();

export default AuthorStoreInstance;

注意init函数不是构造函数的一部分。这是因为构建authorStore时,AuthorActions.initAuthors的回调尚未向调度程序注册。

在向调度程序注册回调后,应该进行初始化。

编辑:为清楚起见,initAuthors看起来像这样:

initAuthors() {
    var authors = AuthorAPI.getAllAuthors();

    Dispatcher.dispatch({
        actionType: ActionTypes.INITIALIZE,
        initialData: {
            authors: authors
        }
    });
}