为啥这个分配不触发?
Posted
技术标签:
【中文标题】为啥这个分配不触发?【英文标题】:Why this assign does not trigger?为什么这个分配不触发? 【发布时间】:2021-11-12 11:29:19 【问题描述】:在阅读了official xstate tutorial 之后,我尝试在dev.to by one of the xstate's dev 上的这篇文章的启发下实现我自己的机器。
除了output
似乎没有更新之外,一切都按预期工作。我认为这项任务没有完成它的工作。我忘记了什么?
为了比较,这里有一个来自 xstate 的工作 demo,其中上下文中的变量按预期更新。
在Context | XState Docs上分配的更多信息
我的代码:
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);
【问题讨论】:
【参考方案1】:然后您需要返回一个 Promise,并在 Promise 解决后让状态机更新上下文。
上下文在invoke
的onDone
属性中更新。
const fetchMachine = createMachine<FetchContext>(
initial: "idle",
context:
output: "wesh" // none selected
,
states:
idle:
on:
FETCH: "loading"
,
loading:
invoke:
src: (context, event) => async (send) =>
return new Promise((resolve, reject) =>
setTimeout(async () =>
try
const data = await fetchifetch();
resolve(data.title);
catch (err)
reject(err);
, 4000);
);
,
onDone:
target: "fetch",
actions: assign(
output: (_, event) => event.data,
)
,
onError:
target: "idle"
,
on:
FETCHED_SUCCESSFULLY:
target: "idle",
,
fetch:
on:
CLOSE: "idle"
);
【讨论】:
我们可以写invoke: src: fetchifetch, onDone: target: "fetch", actions: assign( output: (_, event) => event.data.title ), onError: target: "idle"
是的,我推测超时的原因是为了模拟长时间的延迟
是的,我为此添加了 :)以上是关于为啥这个分配不触发?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个 (null || !TryParse) 条件会导致“使用未分配的局部变量”?