After reading the official xstate tutorial, I tried to implement my own machine inspired by this post on dev.to by one of the xstate's dev.
Everything works as expected besides that output
does not seem to be updated. The assignment does not do its job I think. What did I forget?
To compare, here is a working demo from xstate where the variable in the context is updated as expected.
more information on assign on Context | XState Docs
my code:
import "./styles.css";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { createMachine, assign } from "xstate";
import { useMachine } from "@xstate/react";
interface FetchContext {
output: string;
}
const fetchifetch = async () => {
return await fetch(
"https://jsonplaceholder.typicode.com/todos/1"
).then((response) => response.json());
};
const fetchMachine = createMachine<FetchContext>({
initial: "idle",
context: {
output: "wesh" // none selected
},
states: {
idle: {
on: {
FETCH: "loading"
}
},
loading: {
invoke: {
src: (context, event) => async (send) => {
setTimeout(async () => {
const data = await fetchifetch();
console.log("done");
console.log(data);
// well. here I want to assign something to output
assign({
output: (context, event) => data.title
});
send("FETCHED_SUCCESSFULLY");
}, 4000);
console.log("start");
},
onError: {
target: "idle"
}
},
on: {
FETCHED_SUCCESSFULLY: {
target: "idle"
}
}
},
fetch: {
on: {
CLOSE: "idle"
}
}
}
});
function App() {
const [current, send] = useMachine(fetchMachine);
const { output } = current.context;
return (
<div className="App">
<h1>XState React Template</h1>
<br />
<input
disabled={current.matches("loading")}
defaultValue="yo"
onChange={(e) => console.log(e.currentTarget.value)}
/>
<button
disabled={current.matches("loading")}
onClick={() => send("FETCH")}
>
click to fetch
</button>
<!-- let's display the result over here -->
<div>{output}</div>
<div>{current.context.output}</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);