【问题标题】:React + Flux: Getting initial state into a storeReact + Flux:将初始状态放入商店
【发布时间】:2015-05-11 13:41:27
【问题描述】:

我们最近从 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 反模式?

【问题讨论】:

  • 感觉就像你在那个商店的反模式边缘。不过,Flux 的伟大之处在于,它更像是一个架构概念,而不仅仅是一个组件。这意味着您可以通过多种方式创建商店并将其保留在 Flux 精神中。在我从事的一个项目中,我们只使用了 Flux 库中的调度程序,这意味着商店没有像您的示例那样初始化。商店只是在需要数据时填充自己(来自组件或路由器的操作)。我不认为你的例子是不好的做法,但它开启了一个很好的讨论。
  • 是的,我希望围绕这个展开一些讨论,因为我也有这种感觉,但我需要更具体的东西:)

标签: javascript reactjs reactjs-flux refluxjs


【解决方案1】:

您使用getInitialState() 更改商店的状态对我来说是错误的。您至少应该在componentWillMount 中这样做。

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

【讨论】:

  • 添加到您的答案中,我建议您花一些时间研究facebook's chat app。它几乎涵盖了所有内容。
  • 看起来聊天应用程序在getInitialState 中获得了初始状态,而不是建议的componentWillMount
【解决方案2】:

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>);
    }
});

【讨论】:

  • 感谢您的回答 - 我有点困惑。在您的示例中,您似乎没有将初始状态发送到商店,而是从商店获取它?在我的示例中,我需要将提供给我的组件的属性“initialA”放入我的商店。我错过了什么吗?
  • @MarkusCoetzee 那么你为什么要从组件而不是商店设置initialA
  • 组件接收这个属性(从父容器传下来)。此属性构成组件初始状态的一部分。我的问题是关于将这个初始状态放入商店的 Flux 方式是什么
  • 好的,我会将商店拉到父组件。在那里进行初始状态处理并通过道具传递数据。
  • 我相信@Spoike 指的是创建一个父组件,该组件仅执行数据获取部分,并将道具传送到其中的组件。这是一种已经出现的惯例,甚至 Facebook 也在内部进行。这不是“Fluxy”之类的东西,也不是反模式。犹太反应。查看 Michael Chan 写的关于容器的文章:medium.com/@learnreact/container-components-c0e67432e005
【解决方案3】:

就像其他发帖人所说,最好的办法是在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-01-25
    • 2019-09-23
    • 2016-09-16
    • 2018-12-25
    • 2020-11-02
    • 2015-09-13
    • 2019-01-04
    • 2021-03-21
    • 1970-01-01
    相关资源
    最近更新 更多