I have been using React for a long time and I would like to give a chance to Reason React. I created then a small project to fetch data from a Github repository and then display results.
I would like to use React Hooks and store results into my state.
Here's what I'm trying to do:
type githubRepo = {
name: string,
url: string,
};
module Decode = {
let repo = (repo): githubRepo =>
Json.Decode.{
name: repo |> field("name", string),
url: repo |> field("url", string),
};
};
let useFetch = (~url: string, ~options=?, ()) => {
let (loading, setLoading) = React.useState(() => true);
let (result, setResult) = React.useState(() => []);
React.useEffect1(
() => {
ignore(
Js.Promise.(
Fetch.fetch(url)
|> then_(Fetch.Response.json)
|> then_(json =>
json
|> Decode.repo
|> (
decodedRepo => {
Js.log(decodedRepo);
setResult(result => decodedRepo);
setLoading(_ => false);
Some(decodedRepo);
}
)
|> resolve
)
|> catch(_err => resolve(None))
),
);
None;
},
[||],
);
(loading, result);
};
When I try to do setResult(_ => decodedRepo)
it throws an error
This has type: githubRepo But somewhere wanted: list('a)
I know I've initialized my React.useState to an empty list but I can't figure out how to set my decodedRepo
inside.
Here's the result of Js.log(decodedRepo)
:
Array [ "Node.js", "https://api.github.com/orgs/nodejs" ]
0: "Node.js"
1: "https://api.github.com/orgs/nodejs"
length: 2
I would also like to know if there is a way to init useState with no value?
You can prepend an item to a list by using the list spread syntax, similarly to how you would in JavaScript:
setResult(result => [decodedRepo, ...result]);
But if you don't want to deal with the possibility of more than one item, you need to use a container that is restricted to either zero or one item only. This is the option
type. In use it would look something like this:
let (result, setResult) = React.useState(() => None);
setResult(result => Some(decodedRepo));
Then when you use result
you are forced to deal with the possibility that it may or may not contain an item:
switch (result) {
| Some(decodedRepo) => ...
| None => ...
}