问题描述
我正在尝试使用 Firebase 保持状态。我目前正在使用“saveState”函数,该函数运行良好,并将最新状态正确保存到 Firebase。
现在我希望能够根据 Firebase 中最近保存的状态初始化状态机。在下面的代码中,我试图使用我的“loadState”函数为 Xstate 提供一个配置对象。它目前返回一个带有正确状态配置的承诺。
这是我的“saveState”代码:
//This function works fine.
function saveState(current,id){
let transactionjsON = serialize(current);
transactionjsON['createdOn'] = new Date();
return firebase.saveTransactionState({transactionjsON,transactionId:id});
}
这是我的“loadState”函数,它从 Firebase 返回一个包含正确配置信息的承诺。
function loadState(id){
return firebase.getTransactionState({transactionId:id}).then(function(querySnapshot) {
return querySnapshot.docs.map(doc => deserialize({...doc.data()}) );
});
};
现在我的问题是尝试使用上述“loadState”函数加载 Xstate。在这里,我尝试使用 useMachine React 钩子:
const [current,send] = useMachine(transactionMachine,{
state: () => loadState(id),//Trying to do something like this,but it doesn't seem to work.
actions:{
save: () => saveState(current,id),},});
我最终得到了错误:“TypeError:无法读取未定义的属性‘数据’”,我认为这是因为承诺尚未解决导致尝试读取未定义的值。
这到底是可能的还是我做错了?
我对这一切都很陌生,任何指导将不胜感激。谢谢。
解决方法
我想您可以使用 useEffect
来更新您的状态机。
在状态机中调用 fetch 怎么样?
import { Machine,assign } from 'xstate';
const yourMachine = Machine({
id: 'yourStateMachine',initial: 'fetching',context: {
values: {
id: '',// likely need a state to initialize this value before fetching
apiDat: {}
},},states: {
fetching: {
invoke: {
src: ({values}) => firebase
.getTransactionState({ transactionId: values.id })
.then(function(querySnapshot) {
return querySnapshot.docs.map(
doc => deserialize({...doc.data()})
);
}),onDone: { target: 'resolving',actions: 'cacheApiDat' },onError: { target: 'error.fetchFailed' },}
},resolving: {
initial: 'delay',states: {
delay: {
after: {
750: 'resolve'
},resolve: {
always: [
{ cond: 'isSuccess',target: '#yourStateMachine.idle' },{ cond: 'isUnauthorized',target: '#yourStateMachine.error.auth' },],}
},error: {
states: {
fetchFailed: {
type: 'final',auth: {
type: 'final',}
}
},idle: {
},}
},{
actions: {
cacheApiDat: assign({ values: ({values},event) => ({
...values,apiDat: event.data,// save whatever values you need here
}),}),guards: {
// this requires a definition based on firebase's returned api call on a success
isSuccess: ({values}) => typeof values.apiDat.data !== 'undefined',// this requires a definition based on firebase's returned api call when the call is unauthorized
isUnauthorized: ({values}) => typeof values.apiDat.detail !== 'undefined' && values.apiDat.detail === 'invalid_auth',}
});