[@bs.val] external fetch: string => Js.Promise.t('a) = "fetch"; type state = | LoadingDogs | ErrorFetchingDogs | LoadedDogs(array(string)); [@react.component] let make = () => { let (state, setState) = React.useState(() => LoadingDogs); // Notice that instead of `useEffect`, we have `useEffect0`. See // reasonml.github.io/reason-react/docs/en/components#hooks for more info React.useEffect0(() => { Js.Promise.( fetch("https://dog.ceo/api/breeds/image/random/3") |> then_(response => response##json()) |> then_(jsonResponse => { setState(_previousState => LoadedDogs(jsonResponse##message)); Js.Promise.resolve(); }) |> catch(_err => { setState(_previousState => ErrorFetchingDogs); Js.Promise.resolve(); }) |> ignore ); // Returning None, instead of Some(() => ...), means we don't have any // cleanup to do before unmounting. That's not 100% true. We should // technically cancel the promise. Unofortunately, there's currently no // way to cancel a promise. Promises in general should be way less used // for React components; but since folks do use them, we provide such an // example here. In reality, this fetch should just be a plain callback, // with a cancellation API None; });