如何在 Immutablejs 和 Redux 以及 Flux 和 React 中设置类似 Ember 的计算属性

Posted

技术标签:

【中文标题】如何在 Immutablejs 和 Redux 以及 Flux 和 React 中设置类似 Ember 的计算属性【英文标题】:How to setup Ember like computed properties in Immutablejs and Redux and Flux and React 【发布时间】:2015-10-13 10:00:00 【问题描述】:

我习惯于计算Ember Object Model 中的属性。这是一种指定依赖于其他属性的计算属性的便捷方式。

假设fullName 依赖于firstNamelastName,我可以将计算属性设置为函数computeProperties,并在每次进行更改时调用computeProperties

例子:

function computeFullName(state) 
  const fullName = state.get('firstName') + state.get('lastName');
  const nextState = state.set('fullName', fullName);
  return nextState;


function computeProperties(state) 
  const nextState = computeFullName(state);
  return nextState;


// store action handler
[handleActionX](state) 

  let nextState = state.set('firstName', 'John');
  nextState = state.set('lastName', 'Doe');

  nextState = computeProperties(nextState);

  return nextState;

有没有办法自动设置计算属性,这样我就不必每次都调用额外的函数了。在 Redux 或 ImmutableJS 中。

【问题讨论】:

【参考方案1】:

要创建计算属性,您可以使用独立的 observable 库 mobservable。

var user = mobservable.props(
  firstName: 'John',
  lastName: 'Doe',
  fullName: function() 
    return this.firstName + this.lastName
  
);

var nameViewer = mobservable.ObservingComponent(React.createClass(
   render: function() 
       return (<span>user.fullName</span>)
   
);

这应该是它的要点,现在对 user.firstName 或 lastName 的任何更改都会重新呈现您的 nameViewer 组件。您可以进一步将其与 redux 等通量实现结合以更改数据,并将用户本身推送到您的组件树中。但请注意,用户对象本身不是不可变的(在这种情况下,它毕竟是不可观察的;-))另请参阅 trivial 和 slightly more interesting fiddles 以获取一些示例。 p>

【讨论】:

我需要一个包含不可变库的解决方案 在这种情况下,我认为您必须在您的商店中手动编码此类逻辑,或者,这更像是一种反应方式,作为从您的组件中使用的(实用程序)函数,基于真实数据,以便在每次渲染期间更新值。 我应该将计算状态保留在存储中还是反应组件状态? @mweststrate 哲学是尽可能不存储计算状态:)否则它取决于我认为的重用量,如果其他组件不重用计算,我会将其置于组件状态,否则在商店里。【参考方案2】:

查看reselect。可组合的纯函数,用于有效计算来自商店的派生数据。 Afaik 计划在某个阶段将 reselect 的选择器引入 Redux 核心,如果它们被证明很受欢迎的话。在自述文件的底部也有一个使用 ImmutableJS 的示例。

【讨论】:

【参考方案3】:

这里是 Redux 作者!

Using reselect as suggested by WildService 是要走的路。我认为我们不会将它包含在核心中,因为 reselect 可以很好地完成它的工作,而且我们可以将它作为一个单独的库。

我想说明几点:

即使重新选择,您也不希望在 reducer 内计算数据。选择器应该由reducer管理的状态。换句话说,选择器是您的 Redux 存储状态和组件之间的步骤——它们不在您的 reducer 中。保持 Redux 状态标准化以便更新是很重要的。

我们实际上鼓励您定义选择器相关的 reducer,这样当您更改状态形状时,您不必更改组件 ——他们会改用选择器。您可以在Redux folder of Flux Comparison

中看到这样的示例

我们有一个documentation page introducing reselect and describing how to use it for computing derived data。看看吧。

【讨论】:

【参考方案4】:

这样的事情呢?

export const getWidgetsWithComputedProps = widgets => 
  return widgets.map(w => getWidgetWithComputedProps(w));
;

export const selectWidgetType = widget => 
  switch (widget.type) 
    case 'line':
      return 'time-series';
    case 'pie':
    case 'bar':
      return 'cross-sectional';
    default:
      console.warn('Back up: that type of widget does not exist!', widget.type);
      return null;
  
;

export const getWidgetWithComputedProps = createSelector(
  widget => widget,
  selectWidgetType,
  (widget, _type) => 
    return ...widget, _type
  
);

【讨论】:

以上是关于如何在 Immutablejs 和 Redux 以及 Flux 和 React 中设置类似 Ember 的计算属性的主要内容,如果未能解决你的问题,请参考以下文章

combineReducers 破坏 Redux 状态并破坏多个 ImmutableJs 减速器

React-Native + Redux + ImmutableJS内存泄漏

ImmutableJS 映射到 javascript 对象

React / Redux 中树结构和 shouldComponentUpdate 的性能问题

前端日记 -----简单记录一下自己浏览的前端文章

Redux 中的 React ReRender