13

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

采用一个容器组件将所有状态作为属性向下传递组件树的方法并不是为我们开发应用程序的实用方法,因为该应用程序使用了类似页面的大型模式。确实有足够的状态传递给模态,以便他们将数据加载到他们的存储中。

我遇到的问题是我需要将一些初始状态(作为道具传递)到模态组件的存储中。在这篇文章中,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 反模式?

4

3 回答 3

12

我觉得你getInitialState()用来改变商店的状态是错误的。你至少应该在componentWillMount.

我会触发一个动作componentWillMount并让存储处理程序更新存储的内部状态(这应该总是不断变化的情况)。然后,您的组件的存储更改处理程序可以使用您当前称为“初始状态”的任何数据

于 2015-03-10T19:25:05.670 回答
4

Reflux.listenTo当您提供第三个参数并且Reflux.connectmixin 工厂(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>);
    }
});
于 2015-03-11T10:46:43.660 回答
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
        }
    });
}
于 2017-11-11T19:22:26.710 回答