无法为xstate创建子状态

时间:2020-05-16 09:13:20

标签: xstate

我创建了this codesandbox来突出问题。

我已经创建了一个状态机来进行React hook可中止的提取。

使它起作用的唯一方法是使所有状态都处于同一级别:

export interface AbortableSchema {
  states: {
    [AbortableStates.Idle]: {};
    [AbortableStates.Loading]: {};
    [AbortableStates.Succeded]: {};
    [AbortableStates.Error]: {};
    [AbortableStates.Aborted]: {};
  };
}

export const createAbortableMachine = <D>(): StateMachine<
  AbortableState<D>,
  AbortableSchema,
  AbortableActions<D>
> => {
  const context: AbortableState<D> = {
    state: AbortableStates.Idle,
    data: undefined,
    error: undefined
  };

  const abortableMachine = Machine<
    AbortableState<D>,
    AbortableSchema,
    AbortableActions<D>
  >({
    id: "fetchable",
    initial: AbortableStates.Idle,
    context,
    states: {
      [AbortableStates.Idle]: {
        on: { START: AbortableStates.Loading }
      },
      [AbortableStates.Loading]: {
        on: {
          [AbortableActionTypes.Success]: {
            target: AbortableStates.Succeded,
            actions: (context, event) => {
              context.data = { ...event.payload };
            }
          },
          [AbortableActionTypes.Error]: {
            target: [AbortableStates.Error],
            actions: (context, event) => {
              context.error = { ...event.error };
            }
          },
          [AbortableActionTypes.Abort]: {
            target: [AbortableStates.Aborted]
          }
        }
      },
      [AbortableStates.Succeded]: {
        on: {
          [AbortableActionTypes.Reset]: {
            target: AbortableStates.Idle,
            actions: (_context, event) => {
              _context = context;
              return _context;
            }
          }
        }
      },
      [AbortableStates.Error]: {
        on: {
          [AbortableActionTypes.Reset]: {
            target: AbortableStates.Idle,
            actions: (_context, event) => {
              _context = context;
              return _context;
            }
          }
        }
      },
      [AbortableStates.Aborted]: {
        on: {
          [AbortableActionTypes.Reset]: {
            target: AbortableStates.Idle,
            actions: (_context, event) => {
              _context = context;
              return _context;
            }
          }
        }
      }
    }
  });

  return abortableMachine;
};

但是对我来说,嵌套这样的状态更有意义:

export interface AbortableSchema {
  states: {
    [AbortableStates.Idle]: {};
    [AbortableStates.Loading]: {
      states: {
        [AbortableStates.Succeded]: {};
        [AbortableStates.Error]: {};
        [AbortableStates.Aborted]: {};
      };
    };
  };
}

export const createAbortableMachine = <D>(): StateMachine<
  AbortableState<D>,
  AbortableSchema,
  AbortableActions<D>
> => {
  const context: AbortableState<D> = {
    state: AbortableStates.Idle,
    data: undefined,
    error: undefined
  };

  const abortableMachine = Machine<
    AbortableState<D>,
    AbortableSchema,
    AbortableActions<D>
  >({
    id: "fetchable",
    initial: AbortableStates.Idle,
    context,
    states: {
      [AbortableStates.Idle]: {
        on: { START: AbortableStates.Loading }
      },
      [AbortableStates.Loading]: {
        on: {
          [AbortableActionTypes.Success]: {
            target: AbortableStates.Succeded,
            actions: (context, event) => {
              context.data = { ...event.payload };
            }
          },
          [AbortableActionTypes.Error]: {
            target: [AbortableStates.Error],
            actions: (context, event) => {
              context.error = { ...event.error };
            }
          },
          [AbortableActionTypes.Abort]: {
            target: [AbortableStates.Aborted]
          }
        },
        states: {
          [AbortableStates.Succeded]: {
            on: {
              [AbortableActionTypes.Reset]: {
                target: AbortableStates.Idle,
                actions: (_context, event) => {
                  _context = context;
                  return _context;
                }
              }
            }
          },
          [AbortableStates.Error]: {
            on: {
              [AbortableActionTypes.Reset]: {
                target: AbortableStates.Idle,
                actions: (_context, event) => {
                  _context = context;
                  return _context;
                }
              }
            }
          },
          [AbortableStates.Aborted]: {
            on: {
              [AbortableActionTypes.Reset]: {
                target: AbortableStates.Idle,
                actions: (_context, event) => {
                  _context = context;
                  return _context;
                }
              }
            }
          }
        }
      }
    }
  });

  return abortableMachine;
};

加载具有子状态,但如果这样做,则会收到以下错误消息:

状态节点“ fetchable.loading”的无效转换定义: 子状态“成功”在“可获取”上不存在

1 个答案:

答案 0 :(得分:0)

使用状态名称时,它们不是绝对的;他们相对于兄弟姐妹。例如,如果将"success"作为顶级定义的状态,则只能在该状态的同级中引用该确切的字符串;而不是兄弟姐妹的孩子。然后,您必须按ID进行引用。