最简单的办法是直接使用 await。
它既能在顶层使用,也能在 async 函数体内使用。
文档是 Async / Await | ReScript Language Manual (https://rescript-lang.org/docs/manual/async-await)
let resolved: Profile.t = await fetch("")
->Promise.then(Response.json)
->Promise.thenResolve(payload => {
let record = JSON.Decode.object(payload)->Option.getOrThrow
Profile.fromJson(record)
})
不过,一般来说,通过 dispatch 函数触发 reducer 的状态更新是较好的做法。
type model = {
profile: option<Profile.t>,
}
type event = SetProfile(Profile.t)
let reduceState = (model, event) => {
switch event {
| SetProfile(profile) => {
...model,
profile: Some(profile),
}
}
}
@react.component
let make = () => {
let (model, sendAction) = React.useReducer(
reduceState,
{
profile: None,
},
)
React.useEffect(() => {
fetch("")
->Promise.then(Response.json)
->Promise.thenResolve(payload => {
let record = JSON.Decode.object(payload)->Option.getOrThrow
let profile = Profile.fromJson(record)
sendAction(SetProfile(profile))
})
->Promise.ignore
None
}, [sendAction])
switch model.profile {
| Some(profile) => <div> {React.string("Profile ready")} </div>
| None => <div> {React.string("Waiting...")} </div>
}
}
从英语翻译·查看原文Simplest approach: Use await directly.
It works at the top level as well as within an async function's body.
Documentation: Async / Await | ReScript Language Manual (https://rescript-lang.org/docs/manual/async-await)
let resolved: Profile.t = await fetch("")
->Promise.then(Response.json)
->Promise.thenResolve(payload => {
let record = JSON.Decode.object(payload)->Option.getOrThrow
Profile.fromJson(record)
})
In general though, it's good practice to trigger reducer state updates through a dispatch function:
type model = {
profile: option<Profile.t>,
}
type event = SetProfile(Profile.t)
let reduceState = (model, event) => {
switch event {
| SetProfile(profile) => {
...model,
profile: Some(profile),
}
}
}
@react.component
let make = () => {
let (model, sendAction) = React.useReducer(
reduceState,
{
profile: None,
},
)
React.useEffect(() => {
fetch("")
->Promise.then(Response.json)
->Promise.thenResolve(payload => {
let record = JSON.Decode.object(payload)->Option.getOrThrow
let profile = Profile.fromJson(record)
sendAction(SetProfile(profile))
})
->Promise.ignore
None
}, [sendAction])
switch model.profile {
| Some(profile) => <div> {React.string("Profile ready")} </div>
| None => <div> {React.string("Waiting...")} </div>
}
}