模型助手属于React / Flux的位置?

时间:2015-09-22 21:02:36

标签: javascript reactjs reactjs-flux flux

在尝试将我的大脑包裹在React和Flux周围的时候,我很难决定把我所说的“#34;模型助手”#34;方法。

例如,考虑到有一个" Person"商店中包含的实体,并且该人具有"名字"和#34;姓氏",哪里是最合乎逻辑的地方放一个"全名"简单地将两者连接在一起的辅助方法?我的直觉说,最好有全名"在商店内,但我不确定。如果是这样,它会在商店中更新此值,还是应该在商店本身内计算?

是否有可以接受这种功能的地方?

谢谢!

3 个答案:

答案 0 :(得分:1)

除了@Christian的回答(我同意),您可以使用object-assign模块在​​商店中使用常见帮助:https://www.npmjs.com/package/object-assign

这是我的一个商店的部分示例,其中包含帮助方法(例如isAuthenticatedgetUsername)使用object-assignStatusMixin合并到每个商店中:

var AuthStore = assign({}, StatusMixin, EventEmitter.prototype, {
  isAuthenticated: function () {
    return _data.get(TOKEN_KEY) ? true : false;
  },

  getUsername() {
    return _data.get(USERNAME_KEY);
  },

  getToken() {
    return _data.get(TOKEN_KEY);
  },

  invalidate() {
    _data = _data.clear(); 
    this.setStatus(''); //this method is from the StatusMixin!
    this.emitChange(Constants.CHANGED);
  },

  emitChange: function() {
    LocalStorage.set(Constants.ls.AUTH_STORE, {
      auth_token: _data.get(TOKEN_KEY),
      username: _data.get(USERNAME_KEY)
    });
    this.emit(Constants.CHANGED);
  },

  addChangeListener: function(callback) {
    this.on(Constants.CHANGED, callback);
  },

  removeChangeListener: function(callback) {
    this.removeListener(Constants.CHANGED, callback);
  },

  getState: function()  {
    return _data;
  }
});

和(完整)StatusMixin

'use strict';

var logger = require('../../util/Logger');

var StatusMixin = {
  _status: '',
  getStatus: function() {
    return this._status;
  },
  setStatus(status) {
    this._status = status;
  }
};

module.exports = StatusMixin;

现在,我可以在不在每个商店上编写AuthStore.setStatus(Constants.request.PENDING);方法的情况下调用setStatus(我为每个商店执行此操作)。

答案 1 :(得分:1)

通常,这里的“最佳实践”是创建一个高阶组件,它提供辅助函数或连接的全名作为需要此修改值的组件的支柱。

function giveFullName(Component) {
  const ComponentWithFullName = React.createClass({
    render() {
      return <Component {...this.props} fullName={this.props.firstName+" "+this.props.lastName} />;
    }
  });
  return ComponentWithFullName;
};

var PersonPage = React.createClass({

  render() {
    var { name } = this.props.fullName; // get fullName from props
    return <div>{'Hello '+(name ? name : 'Mystery Stranger')}</div>;
  }
});
PersonPage = ComponentWithFullName(PersonPage)
});

我不同意@ cristian的回答,因为ReactJS的优势之一是关注应用程序信息流的强烈分离和易于推理。如果我们在商店中放置一个帮助器方法,那么我们不知道什么时候看到全名,它是否是商店的全名,或者是一个组件通过连接同一商店的名字和姓氏来创建自己的全名。但是,如果不在商店中放置此全名功能,那么我们知道任何全名来自组件。创建可提供此功能的更高阶组件可实现相同的DRY原则,同时保持清楚地说明值/ UI元素来自何处的能力。

有关Hoact中有关HoC vs Mixins的更多信息,请参阅https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750,以及为什么您应该支持HoCs。

答案 2 :(得分:1)

为了使事情易于管理,特别是如果您有许多商店和大型组件树,请尝试关注商店和组件的功能:

  1. 商店用于a)存储数据(名字,姓氏,非衍生数据),以及b)为组件提供数据(包括派生数据)。
  2. 组件用于向用户呈现a)数据,b)用于与数据交互的锚点。
  3. 我会尽量避免操纵组件树中的数据。并建议任何组件中的任何数据道具始终来自商店。它们从较高的组件传递下来,但在此过程中没有被操纵。

    如果辅助函数仅处理数据(例如,计算组中的总人数),请将它们存放在商店中。 如果他们处理表示逻辑(例如页面上第一人的字体大小应该更大),则将它们放在一个单独的位置。我把它们放在单独的实用程序中导入。 但只能在尽可能低的组件中调用这些函数。

    这样,您的代码可以保持更加可维护。

    数据助手和表示逻辑之间存在很多灰色区域,因此在这种情况下您的选择很难说。但只要您始终如一地应用自己的逻辑,您的代码就可以管理。

    这样,当一个组件给你带来问题时,将道具追踪到它们的源码或者应用于组件中那些道具的功能代码会更容易。

    所以也许是一个具有全名功能的高阶组件,但我不会让更高阶的组件创建一个新的道具。