历史 History

历史状态节点 是一种特殊的状态节点,当它到达时,告诉状态机转到该区域的最后一个状态值。 有两种类型的历史状态:

  • 'shallow', 仅指定顶级历史值,或
  • 'deep', 它指定顶级和所有子级历史值。

历史状态配置

历史状态的配置与原子状态节点相同,但有一些额外的属性:

  • type: 'history' 指定这是一个历史状态节点
  • history (‘shallow’ | ‘deep’) - 无论历史是 shallow 还是 deep 的。 默认为 ‘shallow’。
  • target (StateValue) - 如果不存在历史记录,则为默认目标。 默认为父节点的初始状态值。

考虑以下(人为的)状态图:

  1. const fanMachine = createMachine({
  2. id: 'fan',
  3. initial: 'fanOff',
  4. states: {
  5. fanOff: {
  6. on: {
  7. // 转换到历史状态
  8. POWER: { target: 'fanOn.hist' },
  9. HIGH_POWER: { target: 'fanOn.highPowerHist' }
  10. }
  11. },
  12. fanOn: {
  13. initial: 'first',
  14. states: {
  15. first: {
  16. on: {
  17. SWITCH: { target: 'second' }
  18. }
  19. },
  20. second: {
  21. on: {
  22. SWITCH: { target: 'third' }
  23. }
  24. },
  25. third: {},
  26. // 浅历史状态
  27. hist: {
  28. type: 'history',
  29. history: 'shallow' // optional; default is 'shallow'
  30. },
  31. // 默认的浅历史状态
  32. highPowerHist: {
  33. type: 'history',
  34. target: 'third'
  35. }
  36. },
  37. on: {
  38. POWER: { target: 'fanOff' }
  39. }
  40. }
  41. }
  42. });

在上面的状态机中,从事件 'POWER' 上的 'fanOff' 转换到 'fanOn.hist' 状态,该状态被定义为浅历史状态。 这意味着状态机应该转换到 'fanOn' 态以及 'fanOn' 的前一个子状态。 默认情况下,如果没有历史状态,'fanOn' 将进入它的初始状态,'first'

  1. const firstState = fanMachine.transition(fanMachine.initialState, {
  2. type: 'POWER'
  3. });
  4. console.log(firstState.value);
  5. // 由于没有历史记录,因此转换到 'fanOn' 的初始状态
  6. // => {
  7. // fanOn: 'first'
  8. // }
  9. const secondState = fanMachine.transition(firstState, { type: 'SWITCH' });
  10. console.log(secondState.value);
  11. // => {
  12. // fanOn: 'second'
  13. // }
  14. const thirdState = fanMachine.transition(secondState, { type: 'POWER' });
  15. console.log(thirdState.value);
  16. // => 'fanOff'
  17. console.log(thirdState.history);
  18. // => State {
  19. // value: { fanOn: 'second' },
  20. // actions: []
  21. // }
  22. const fourthState = fanMachine.transition(thirdState, { type: 'POWER' });
  23. console.log(fourthState.value);
  24. // 从历史转换为 'fanOn.second'
  25. // => {
  26. // fanOn: 'second'
  27. // }

指定了 target 后,如果定义历史状态的 state 区域不存在历史,则默认情况下它将进入 target 状态:

  1. const firstState = fanMachine.transition(fanMachine.initialState, {
  2. type: 'HIGH_POWER'
  3. });
  4. console.log(firstState.value);
  5. // 由于没有历史记录,因此转换到 'fanOn.third' 的目标状态
  6. // => {
  7. // fanOn: 'third'
  8. // }

注意

  • 历史状态可以直接从 state.history 上的 State 实例访问,但这很少是必要的。