I’ll do my best to explain my end goal here. I’m taking a React Hooks tutorial and implementing it in ReasonReact. It’s gone well so far:
- Axios for request
- bs-json for decoding
- React.useState for search field text.
My issue is with using React.useState
with an array or list.
When I decode the JSON received, I end up with an array(book)
. My intial value for React.useState
is array(book)
, just like my decoded books. But when I compile, the code that is calling setBooks
has an error:
This expression has type array(book)
but an expression was expected of type array(book) => array(book)
I’m stuck and I’m still new to a lot of ReasonML. I get it’s expecting an array(book), but I thought that’s what I was giving it.
Code below:
type volumeInfo = {
title: string,
publishedDate: string,
};
type book = {
id: string,
meta: volumeInfo,
};
type books = {
items: array(book),
};
module Decode = {
let volumeInfo = volumeInfo =>
Json.Decode.{
title: volumeInfo |> field("title", string),
publishedDate: volumeInfo |> field("publishedDate", string),
};
let book = book =>
Json.Decode.{
id: book |> field("id", string),
meta: book |> field("volumeInfo", volumeInfo),
};
let books = books =>
Json.Decode.{
items: books |> field("items", array(book)),
};
};
[@react.component]
let make = () => {
let (searchTerm, setSearchTerm) = React.useState(() => "");
let (books, setBooks) = React.useState(() => {
let bookItems : array(book) = [||];
bookItems;
});
let fetchBooks = () =>
Js.Promise.(
Axios.get("https://www.googleapis.com/books/v1/volumes?q=" ++ searchTerm)
|> then_(response => response##data)
|> then_(json =>
json |> Decode.books
|> (decodedBooks => {
Js.log(decodedBooks.items[0].meta.title);
setBooks(decodedBooks.items); // is array(book), expecting array(book)
})
|> resolve
)
// |> then_(response => resolve(setBooks(response##data)))
|> catch(error => resolve(Js.log(error)))
);
let onSearchTermChange = (event) => {
setSearchTerm(ReactEvent.Form.target(event)##value);
};
let onSubmitSearchForm = (event) => {
fetchBooks();
ReactEvent.Mouse.preventDefault(event);
};
<section>
<form action="?">
<label>
<span>{ReasonReact.string("Search for Books")}</span>
<input
placeholder="microservice, restful, etc"
value=(searchTerm)
onChange=(onSearchTermChange)
/>
<button onClick=(onSubmitSearchForm)>
{ReasonReact.string("Search")}
</button>
</label>
</form>
</section>
};