producer中返回新数据

在之前的示例中,producer函数中是只需要对draft参数进行操作,不需要从中返回任何内容的,如果需要返回数据,通常也只是返回draft。但是在一些特定的需求下,从producer中返回其他数据也是十分有意义的。

例如在以下示例中,有一些返回操作是可以使用的,而有一些返回操作是不必要的。具体哪些操作在Immer中是可以使用的,可以直接参考一下示例中的说明。

import produce, { nothing } from 'immer';

const todos = produce((draft, action) => {
  switch (action.type) {
    case 'add':
      // 这是Immer中标准的写法,函数无需返回任何内容。
      draft.push(action.payload);
      return;
    case 'edit':
      // 在函数中直接返回draft与不返回任何内容的效果是等价的。
      // 但是这种用法没有任何意义,只是多敲了几个字母。
      const todo = draft.find(t => t.id === action.payload.id);
      todo.title = action.payload.title;
      return draft;
    case 'load':
      // 这里直接返回了一个全新的数据状态,新的数据状态会替代draft中携带的数据状态。
      return action.payload;
    case 'redefine':
      // 这种用法是不可以的,直接重新声明draft的内容不能修改draft中携带的状态,
      // 也不能让produce函数返回新的状态。
      draft = [{ id: 1, title: 'new todo', complete: false }];
      return;
    case 'editNnew':
      // 这种用法是不可以的,修改一个draft的同时返回一个全新的状态是不被允许的。
      draft[2].complete = !draft[2].complete;
      return [{ id: 1, title: 'new todo', complete: false }, ...draft];
    case 'redefine-exp':
      // 这种用法可以返回一个新的状态,但是这种用法完全没有必要,只会增加代码中的复杂度。
      return [{ id: 1, title: 'new todo', complete: false }, ...draft];
    case 'empty':
      // 这是从produce函数中修改draft内容为undefined的标准写法。
      return nothing;
    case 'empty-alt':
      // 从produce函数中直接返回undefined会让Immer认为producer只是修改并返回了draft,
      // 所以直接返回undefined时实际上返回的依旧还是draft。
      return undefined;
  }
});