【问题标题】:Where do model helpers belong in React/Flux?模型助手在 React/Flux 中属于哪里?
【发布时间】:2015-12-20 00:30:14
【问题描述】:

在尝试围绕 React 和 Flux 进行思考时,我很难决定将我称之为“模型助手”的方法放在哪里有意义。

例如,假设 Store 中包含一个“Person”实体,并且假设这个 Person 有一个“名字”和一个“姓氏”,那么在哪里放置“完整name" 简单地将两者连接在一起的辅助方法?我的直觉说最好在商店中使用“全名”,但不确定。如果是这样,它会是一个 Action 更新 store 中的这个值,还是应该在 Store 本身内计算?

有没有一个可以接受的地方来放置这种功能?

谢谢!

【问题讨论】:

    标签: javascript reactjs reactjs-flux flux


    【解决方案1】:

    为了保持事情的可管理性,特别是如果你有很多商店和一个大的组件树,试着集中你的商店和组件的功能:

    1. 存储用于 a) 存储数据(名字、姓氏,非派生数据),以及 b) 为组件提供数据(包括派生数据)。
    2. 组件用于向用户呈现 a) 数据,以及 b) 与数据交互的锚。

    我会尽量避免在组件树中操作数据。并建议任何组件中的任何数据道具始终来自商店。它们是从更高的组件传下来的,但不会在此过程中被操纵。

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

    这样,您的代码更易于维护。

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

    这样,当一个组件给你问题时,更容易追踪 props 的来源,或者你的组件中应用于这些 props 的函数代码。

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

    【讨论】:

      【解决方案2】:

      所以 store 保存了应用程序的数据和业务逻辑,我看到这个帮助器就像一个应该在你的 store 中发生的操作。您不需要更新全名的操作,一旦第一个和第二个名称可用,它应该由商店本身连接。

      【讨论】:

        【解决方案3】:

        除了@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);(我为每个 Store 调用),而无需在每个 Store 上编写 setStatus 方法。

        【讨论】:

          【解决方案4】:

          通常,这里的“最佳实践”是创建一个高阶组件,该组件提供辅助函数或串联全名作为需要此修改值的组件的道具。

          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 的优势之一是它的关注点分离度很高,并且易于推理应用程序信息流。如果我们在 store 中放置一个 helper 方法,那么我们不知道什么时候看到全名,是来自 store 的全名,还是一个组件通过连接来自同一个 store 的名字和姓氏自己创建的全名.但是,如果不把这个全名函数放在 store 中,那么我们就知道任何全名都来自一个组件。创建一个可以提供此功能的高阶组件可以实现相同的 DRY 原则,同时保持清晰推理值/UI 元素来自何处的能力。

          请参阅https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750,了解有关 React 中的 HoC 与 Mixins 的更多信息,以及为什么您应该偏爱 HoC。

          【讨论】:

            猜你喜欢
            • 2015-08-20
            • 2019-01-15
            • 2015-10-23
            • 1970-01-01
            • 2013-07-29
            • 2015-01-26
            • 2010-09-08
            • 2014-01-26
            • 1970-01-01
            相关资源
            最近更新 更多