我为状态创建了一个通用的reducer,什么时候应该使用它,什么时候不应该使用它

Ani*_* K. 3 javascript reactjs react-native redux react-redux

我有一个redux商店.要更改商店中的数据,通常的方法是创建操作,actionCreator,reducer,然后分派操作.对于中小型应用程序,在很多地方进行更改以反映此类更改看起来有点过分.所以我创建了一个通用的reducer,它看起来像这样:

// here state is a copy of actual state, so I can mutate it directly

    const reducer = ( state, action) => {
      if(action.type == 'SETTER'){
       try{
            return assign(state, action.data.target, action.data.value )
        }
        catch(err){
            console.log('WARNING: the key wasn\'t valid', err)
        }
      }
      return state;

    }
Run Code Online (Sandbox Code Playgroud)

这个assign方法是这样的:

const assign = (obj, prop, value) => {
    if (typeof prop === "string")
        prop = prop.split(".");

    if (prop.length > 1) {
        var e = prop.shift();
        assign(obj[e] , prop, value);
    } else
        obj[prop[0]] = value;
  return obj
}
Run Code Online (Sandbox Code Playgroud)

然后我有一个通用的动作调度程序和一个容器组件,它允许我做这样的事情:

containerComponent.set( 'user.name', 'Roy' )
containerComponent.set( 'order.receiver.address', 'N/A')
Run Code Online (Sandbox Code Playgroud)

set在containerComponent上调用时触发的动作如下所示:

{
  type : 'SETTER',
  data : {
    target : 'user.name',
    value : 'Roy'
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这个通用的reducer允许我再也不会写一个reducer,但是我仍然会在状态发生变化时调度一个动作,所以不会违反redux的任何核心原则.

这种方法是否有任何轻微/重大缺点,特别是在性能方面?而且,你在哪里发现这种方法是有用的.

Tim*_*imo 6

正如您所指出的那样,Redux要求您在应用程序中发生某些事情的位置与实际更新存储以反映此事件的点之间实现多层间接.

这是设计的.

全局状态通常会产生一个问题,即可以从应用程序的任何位置任意更改它,而无需简单的方法来了解方法或原因.是的,Redux商店实际上是全球性的.

通过将发生的事件(由动作表示并由动作的有效负载描述)与影响全局状态(由减速器定义)的问题分开,Redux在一定程度上消除了这个问题.不是允许对全局状态进行任意更改,而是可以进行某些非常具体的更改组合,由明确定义的事件触发,在最好的情况下,附加足够的语义信息以使其能够追溯到其原点.

通过创建一对通用动作和缩减器来破坏Redux的这个核心思想,你失去了Redux的核心优势之一,并且在你的组件和商店之间留下了一系列的间接和抽象,这些都没有真正带来你有什么重大的好处.

众所周知,不创造价值的代码是最好的代码删除.在我看来,你可能会更好地不使用Redux而只是使用组件状态而不是使用Redux的残缺实现.


关于这个主题的有趣读物来自创建Redux的Dan Abramov:您可能不需要Redux.

  • 简而言之,没有重大的性能问题.(无论如何,JS callstack的大小几乎从来都不是大多数JS应用程序中的性能瓶颈.)虽然如果你正在寻找redux使用的"单一数据源"功能,那么你自己实现它并不太难,通过在上下文中放置一个简单的JS对象并在任何地方操作它.Redux的_value_是抽象,这是@Timo在他的回答中得到的.如果您不想要这个价值,并且您对性能感到担忧,那么此时您也可以自己实现一个全局商店. (2认同)
  • 不过,我应该补充说,抽象的价值不是它的显而易见性,而是关于[关注点分离](http://wiki.c2.com/?SeparationOfConcerns)和[单一责任原则](http:// wiki.c2.com/?SingleResponsibilityPrinciple),适用于函数式编程.抽象允许您分别重构您的动作,缩减器和组件; 使用`assign`功能,您可以将该逻辑分发到整个系统,使您的应用程序更难以更改. (2认同)