在尝试围绕 xState 和一般状态机进行研究时,我想知道您将如何向表单状态机提供 API URL 以使其可重用。我目前的解决方案是通过withContext来提供,但是感觉不对。
import { Machine, assign } from 'xstate';
const submitForm = async ({ formData, apiURL }) => {
const res = await fetch(apiURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
const message = await res.text();
return { status: res.status, message };
};
const formMachine = Machine({
id: 'form',
initial: 'idle',
context: {
formData: {},
apiURL: '',
},
states: {
idle: {
on: {
SEND: 'submitted',
INPUT: {
actions: assign({
formData: (ctx, { data }) => ({ ...ctx.formData, ...data }),
}),
},
},
},
submitted: {
id: 'form-submitted',
initial: 'pending',
states: {
pending: {
invoke: {
id: 'submitForm',
src: submitForm,
onDone: {
target: 'success',
actions: assign({
result: (ctx, event) => event.data,
}),
},
onError: {
target: 'failure',
actions: assign({
errorMessage: (ctx, event) => event.data,
}),
},
},
},
success: {},
failure: {
on: {
RETRY: 'pending',
SEND: 'pending',
},
},
},
},
},
});
export default formMachine;
import React from 'react';
import { useMachine } from '@xstate/react';
import formMachine from '../data/machines/form';
const ContactForm = () => {
const contactFormMachine = formMachine.withContext({
formData: {
name: '',
email: '',
message: '',
},
apiURL: '/api/contact',
});
const [current, send] = useMachine(contactFormMachine);
return (
<>
{
current.matches('submitted.success') ? (
<div>Message succesfully sent</div>
) : (
<form onSubmit={
(e) => {
e.preventDefault();
send('SEND');
}
}>
...
</form>
)
}
</>
);
};
export default ContactForm;