Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/454.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将方法放在Redux状态的对象上?_Javascript_Reactjs_Flux_Redux - Fatal编程技术网

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

Javascript 如何将方法放在Redux状态的对象上?,javascript,reactjs,flux,redux,Javascript,Reactjs,Flux,Redux,根据react的状态,应用程序必须是可序列化的。 那上课呢 假设我有一个待办事项应用程序。 每个Todo项都有属性,如name,date等。到目前为止一切正常。 现在我想在不可序列化的对象上使用方法。例如,Todo.rename(),它将重命名Todo并执行许多其他操作 据我所知,我可以在某处声明函数并执行rename(Todo)或者通过propsthis.props.rename(Todo)将该函数传递给组件 我在某处声明.rename()时遇到两个问题: 1) 在哪里?在减速机里?在应用程序

根据react的状态,应用程序必须是可序列化的。 那上课呢

假设我有一个待办事项应用程序。 每个
Todo
项都有属性,如
name
date
等。到目前为止一切正常。 现在我想在不可序列化的对象上使用方法。例如,
Todo.rename()
,它将重命名Todo并执行许多其他操作

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

我在某处声明
.rename()
时遇到两个问题: 1) 在哪里?在减速机里?在应用程序的还原程序中,很难找到所有的
方法都是instance
方法。 2) 传递这个函数。真正地我是否应该通过从所有高级组件手动传递它 每次我有了更多的方法,就加上一大堆样板来传递它? 或者总是这样做,希望我对一种类型的对象只有一个重命名方法。不是
Todo.rename()
Task.rename()
Event.rename()

我觉得那很傻。对象应该知道可以对其执行什么操作,以及以何种方式执行。不是吗


我这里缺少什么?

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

不要将方法放在模型上(例如
TodoItem.rename
),而是编写处理操作的还原程序。这就是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)
      ];
  }
}

如果这仍然没有意义,请通读,因为您似乎对Redux应用程序的结构有错误的想法。

Dan的答案当然是正确的,因为在从头开始编写应用程序时,您应该如何使用Redux。我的回答是基于一种非理想的激励情况,这种情况可能与老年退休金计划的情况类似,以及我如何处理这种情况

我发现自己正在尝试创建一个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;
  }
}
//库A是我不想更改的大型第三方库
//库A要求MyClass的实例具有“complexOperation”方法,并具有属性“A”
图书馆A=班级{
静态释放不复杂操作(myClassInstance){
if(myClassInstance.complexOperation()&&myClassInstance.a<100){
返回true;
}否则{
返回false;
}
}
}
//MyClass是我自己控制的类,我希望存储它的状态并使用redux reducer对其进行更改。
MyClass=类{
构造函数(){
这个。a=0;
}
myComplexOperation(){
返回a>10;
}
}
//这是我的redux reducer,它利用了一个库
功能减速机(状态、动作){
开关(动作类型){
案例更改\u我的\u课程:
const myClassInstancePlain=state.myClassInstance;
//redux已将myClassInstance转换为无方法的普通对象,因此我们需要创建MyClass的新实例,并将普通对象中的属性值分配给新实例。使用lodash库中的assign函数来实现这一点-可能不是最有效的方法
const myClassInstance=u.assign(新的MyClass(),myClassInstancePlain);
//现在我可以将myClassInstance传递给LibraryA,complexOperation方法将可用
if(图书馆安全隔离装置复杂操作(myClassInstance)){
myClassInstance.a=50;
}
//我可以将myClassInstance作为新状态的一部分返回,redux会将其转换为普通对象
返回{
……国家,
myClassInstance
};
违约:
返回状态;
}
}

因此,本例展示了一种将对象与处于redux状态的方法合并为普通对象的方法,然后添加回方法,以便在redux reducer中使用它们。我很想听听丹或其他人对这个模式的想法,或者如何做得更好。我在几个地方见过Dan post,在redux中使用方法存储对象是个坏主意,因此这里的目标是找到一种方法,将对象存储为普通对象,并在需要时以有效的方式附加方法。

我不确定这是否完全相关(上下文使用redux和React),但是我在搜索类似的东西时发现了这个页面,所以我写这篇文章以防万一

我的动机是,我有一些状态对象,我想在其中公开该状态的表示,而不是状态本身。例如(使用Immutable.js),我有一个状态(一个模式),它包含一个或多个字段,每个字段由一个唯一标识符标识并存储在一个映射中,另外还有一个标识符列表,该列表给出了字段的顺序

我真的不想写这样的东西

state.get('field').get(state.get('order').get(nth))
获取除减速器之外的任何位置的第n个字段,以便隐藏内部表示并可以轻松更改

我目前正在做的(这是一个小小的实验)是在与reducer相同的文件中添加一个函数:

schema.mapVisibleState = function (state) {
    return {
        getOrderedFields: () => state.get('order').map((fid) => state.get('fields').get(fid)
    }
}
这在相应的React组件中使用(以及类似动机的schema.bindActionCreators函数):

现在,我可以按照正确的顺序访问组件中的字段,只需使用.props.getOrderedFields()即可,无需担心底层表示。它还有一个额外的特性,即很容易对getOrderedFields()函数进行依赖项注入

此外,由于我对字段状态有类似的结构,我可以扩展它:

schema.mapVisibleState = function (state) {
    return {
        getOrderedFields: () => state.get('order').map((fid) => field.mapVisibleState(state.get('fields').get(fid)),
        getNthField (nth) => field.mapVisibleState(state.get('fields').get(state.get('order').get(nth)))
    }
}
你应该看看那个把手
schema.mapVisibleState = function (state) {
    return {
        getOrderedFields: () => state.get('order').map((fid) => field.mapVisibleState(state.get('fields').get(fid)),
        getNthField (nth) => field.mapVisibleState(state.get('fields').get(state.get('order').get(nth)))
    }
}