# Parallel State Nodes

These XState v4 docs are no longer maintained

XState v5 is out now! Read more about XState v5 (opens new window)

🆕 Find more about parallel states in XState (opens new window) as well as a no-code introduction to parallel states (opens new window).

In statecharts, you can declare a state as a parallel state. This means that all its child states will run at the same time. To learn more, see the section in our introduction to statecharts.

# API

A parallel state node is specified on the machine and/or any nested compound state by setting type: 'parallel'.

For example, the machine below allows the upload and download compound states to be simultaneously active. Imagine that this represents an application where you can download and upload files at the same time:



 

 















 
























const fileMachine = createMachine({
  id: 'file',
  type: 'parallel',
  states: {
    upload: {
      initial: 'idle',
      states: {
        idle: {
          on: {
            INIT_UPLOAD: { target: 'pending' }
          }
        },
        pending: {
          on: {
            UPLOAD_COMPLETE: { target: 'success' }
          }
        },
        success: {}
      }
    },
    download: {
      initial: 'idle',
      states: {
        idle: {
          on: {
            INIT_DOWNLOAD: { target: 'pending' }
          }
        },
        pending: {
          on: {
            DOWNLOAD_COMPLETE: { target: 'success' }
          }
        },
        success: {}
      }
    }
  }
});

console.log(fileMachine.initialState.value);
// => {
//   upload: 'idle',
//   download: 'idle'
// }

A parallel state node's state value is represented as an object. This object state value can be used to further transition to different states in a parallel state node:

console.log(
  fileMachine.transition(
    {
      upload: 'pending',
      download: 'idle'
    },
    { type: 'UPLOAD_COMPLETE' }
  ).value
);
// => {
//   upload: 'success',
//   download: 'idle'
// }

A compound state node can contain parallel state nodes. The configuration is the same for nested state nodes:

const lightMachine = createMachine({
  // not a parallel machine
  id: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: { target: 'yellow' }
      }
    },
    yellow: {
      on: {
        TIMER: { target: 'red' }
      }
    },

    // nested parallel machine
    red: {
      type: 'parallel',
      states: {
        walkSign: {
          initial: 'solid',
          states: {
            solid: {
              on: {
                COUNTDOWN: { target: 'flashing' }
              }
            },
            flashing: {
              on: {
                STOP_COUNTDOWN: { target: 'solid' }
              }
            }
          }
        },
        pedestrian: {
          initial: 'walk',
          states: {
            walk: {
              on: {
                COUNTDOWN: { target: 'wait' }
              }
            },
            wait: {
              on: {
                STOP_COUNTDOWN: { target: 'stop' }
              }
            },
            stop: {
              type: 'final'
            }
          }
        }
      }
    }
  }
});

console.log(lightMachine.transition('yellow', { type: 'TIMER' }).value);
// {
//   red: {
//     walkSign: 'solid',
//     pedestrian: 'walk'
//   }
// }