Чистые функции переходов позволяют вычислить следующее состояние и действия машины состояний без создания живого актора или выполнения каких-либо побочных эффектов. Это полезно для серверных приложений, тестирования и сценариев, где необходимо вычислять переходы состояний без побочных эффектов.
Есть две основные функции, которые вы можете использовать для вычисления переходов состояний:
initialTransition(machine, input?): Возвращает кортеж [initialState, initialActions], который представляет начальное состояние и любые действия входа для машины состояний.
transition(machine, state, event): Возвращает кортеж [nextState, actions], который представляет следующее состояние и любые действия, которые будут выполнены во время перехода.
import{createMachine,initialTransition,transition,}from'xstate';constmachine=createMachine({initial:'pending',states:{pending:{on:{start:{target:'started'},},},started:{entry:{type:'doSomething'},},},});// Получение начального состояния и действийconst[initialState,initialActions]=initialTransition(machine);console.log(initialState.value);// 'pending'console.log(initialActions);// [{ type: 'doSomething', ... }]// Получение следующего состояния и действийconst[nextState,actions]=transition(machine,initialState,{type:'start',// Событие для отправки});console.log(nextState.value);// 'started'console.log(actions);// [{ type: 'doSomething', ... }]
Этот чисто функциональный подход предлагает несколько преимуществ:
Детерминированный: Одинаковый вход всегда производит одинаковый выход
Тестируемый: Легко тестировать логику состояний без управления жизненным циклом акторов
Подходит для сервера: Идеален для серверных рабочих процессов и API-эндпоинтов
Отлаживаемый: Можно инспектировать изменения состояния и действия без побочных эффектов
Возвращает начальное состояние и любые действия входа для машины состояний. Если машина требует input, вы должны передать его как второй аргумент в initialTransition.
import{createMachine,initialTransition,transition,}from'xstate';constmachine=createMachine({initial:'pending',states:{pending:{on:{start:{target:'started'},},},started:{entry:{type:'doSomething'},},},});// Получение начального состояния и действийconst[initialState,initialActions]=initialTransition(machine);// Получение следующего состояния и действийconst[nextState,actions]=transition(machine,initialState,{type:'start',// Событие для отправки});console.log(nextState.value);// 'started'console.log(actions);// [{ type: 'doSomething', ... }]
Действия представляют побочные эффекты, которые будут выполнены во время перехода. Чистые функции захватывают эти действия, но не выполняют их, давая вам полный контроль над тем, когда и как их обрабатывать.
Основное внимание следует уделить пользовательским действиям — действиям, которые вы определяете в своей машине состояний. Они захватываются как объекты действий с type и params:
import{createMachine,setup,transition}from'xstate';constmachine=setup({actions:{sendEmail:(_,params:{to:string;subject:string})=>{// Это не будет выполнено в чистых функцияхconsole.log(`Sending email to ${params.to}: ${params.subject}`);},updateDatabase:(_,params:{userId:string;data:any})=>{// Это не будет выполнено в чистых функцияхconsole.log(`Updating user ${params.userId}`,params.data);},},}).createMachine({initial:'idle',states:{idle:{on:{processUser:{target:'processing',actions:[{type:'sendEmail',params:({event})=>({to:event.email,subject:'Processing started',}),},{type:'updateDatabase',params:({event})=>({userId:event.userId,data:{status:'processing',},}),},],},},},processing:{},},});const[initialState]=initialTransition(machine);const[nextState,actions]=transition(machine,initialState,{type:'processUser',userId:'123',email:'[email protected]',});console.log(actions);// [// {// type: 'sendEmail',// params: { to: '[email protected]', subject: 'Processing started' }// },// {// type: 'updateDatabase',// params: { userId: '123', data: { status: 'processing' } }// }// ]