如何将方法放在Redux状态的对象上?

Yan*_*Yan 46 javascript flux reactjs redux

根据文档反应app的状态必须是可序列化的.那么课程怎么样?

假设我有一个ToDo应用程序.到目前为止,每个Todo项目都具有类似等的属性.现在我想在不可序列化的对象上使用方法.即它会重命名todo并做很多其他的东西.namedateTodo.rename()

据我所知,我可以在某处声明函数,rename(Todo)或者通过props将该函数传递this.props.rename(Todo)给组件.

我在.rename()某处声明了2个问题:1)在哪里?在减速机?would be instance在应用程序周围的reducer中找到所有方法很难.2)传递这个功能.真?我应该从所有更高级别的组件手动传递它吗?每次我有更多的方法添加大量的样板来传递它?或者总是这样做,并希望我对一种类型的对象只有一种重命名方法.不是Todo.rename() Task.rename()Event.rename()

这对我来说似乎很愚蠢.对象应该知道可以对它做什么以及以何种方式.是不是?

我在这里缺少什么?

Dan*_*mov 36

在Redux中,您实际上没有自定义模型.您的状态应该是普通对象(或不可变记录).他们不应该有任何自定义方法.

而不是将方法放在模型上(例如TodoItem.rename),你应该编写处理动作的reducer.这就是Redux的重点.

// Manages single todo item
function todoItem(state, action) {
  switch (action.type) {
    case 'ADD':
      return { name: action.name, complete: false };

    case 'RENAME':
      return { ...state, name: action.name };

    case 'TOGGLE_COMPLETE':
      return { ...state, complete: !state.complete };

    default:
      return state;
  }
}

// Manages a list of todo items
function todoItems(state = [], action) {
  switch (action.type) {
    case 'ADD':
      return [...state, todoItem(undefined, action)];

    case 'REMOVE':
      return [
        ...state.slice(0, action.index),
        ...state.slice(action.index + 1)
      ];

    case 'RENAME':
    case 'TOGGLE_COMPLETE':
      return [
        ...state.slice(0, action.index),
        todoItem(state[action.index], action),
        ...state.slice(action.index + 1)
      ];
  }
}
Run Code Online (Sandbox Code Playgroud)

如果这仍然没有意义,请阅读Redux基础知识教程,因为您似乎对Redux应用程序的结构有错误的想法.

  • 但是如果你想做一些像"获取所有可见的待办事项"的东西,你会在哪里放置过滤功能呢?将该功能添加到州是否合适?或者是不满意的? (9认同)
  • 这是不赞成的.相反,我们建议单独编写此函数以接受state参数.我们将这些函数称为"选择器",实际上它们对Redux中的优化非常重要.查看http://redux.js.org/docs/recipes/ComputingDerivedData.html (8认同)
  • 在大多数面向对象的代码中,方法用于获取数据以及设置数据.例如,Todo项可能具有.getName().其中一些可能有逻辑:getUrgency()方法可能会查看任务到期日期及其优先级,并做一些数学运算来返回答案.应该在哪里定义这些函数,如果不是作为商店中对象的方法? (6认同)
  • 如果您需要对状态中存储的对象使用有用的方法,请定义一个名为"User"的模块,并在其中放入执行User.fullName(user)等有用功能的函数.或"用户(用户).fullName()".不管你想要它,但商店中的数据应该是普通的对象. (4认同)
  • @DanAbramov我很想知道乔希最后一个问题的答案.我正在处理类似的情况,我有一些属性的总和,但在哪里放置而不是类模型.method?在效果模块中?在选择器?什么是最好的?查看我更具体的问题:/sf/ask/3044250611/我试图阻止将"新模型()"放到商店... (3认同)

小智 5

在从头开始编写应用程序时,Dan的答案当然应该是如何使用redux的.我的回答是基于一个非理想的激励情况,可能与OP的情况类似,以及我如何处理它.

我发现自己尝试创建一个redux应用程序,它依赖于redux reducer中的第三方库,它们使用方法对输入对象执行操作,并且我希望将这些输入对象保持在redux状态.这是我在伪代码中的激励情况,以及我如何使用lodash的assign方法"解决"它:

// Library A is a large 3rd party library I don't want to change
// Library A expects instances of MyClass to have a method 'complexOperation', and also to have property 'a'
LibraryA = class {
  static reliesOnComplexOperation(myClassInstance) {
    if (myClassInstance.complexOperation() && myClassInstance.a < 100) {
      return true;
    } else {
      return false;
    }
  }
}

// MyClass is my own class that I control, and I want to store it's state and make changes to it using the redux reducer.
MyClass = class {
  constructor() {
    this.a = 0;
  }
  myComplexOperation() {
    return a > 10;
  }
}

//and here is my redux reducer, making use of Library A
function reducer(state, action) {
  switch (action.type) {
    case CHANGE_MY_CLASS:
      const myClassInstancePlain = state.myClassInstance;
      // redux has converted myClassInstance into a plain object with no methods, so we need to create a new instance of MyClass, and assign property values from the plain object to the new instance. Using the assign function from lodash library to achieve this - likely not the most efficient way
      const myClassInstance = _.assign(new MyClass(), myClassInstancePlain);

      // now I can pass myClassInstance off to LibraryA, and the complexOperation method will be available
      if (LibraryA.reliesOnComplexOperation(myClassInstance)) {
        myClassInstance.a = 50;
      }
      // I can return myClassInstance as part of the new state, and redux will convert it to a plain object
      return {
        ...state,
        myClassInstance
      };
    default:
      return state;
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,此示例显示了将具有redux状态的方法的对象合并为普通对象的一种方法,然后添加回方法,以便可以在redux reducer中使用它们.很想听听丹或其他任何人对这种模式的看法,或者如何做得更好.我见过几个地方是存储对象与方法是终极版一个坏主意丹后期,所以在这里我们的目标是找到一种方法来存储对象作为一个普通的对象,并附加方法时,你需要他们以一种有效的方式.