reasonbucklescriptreason-react

Reason-react rendering list of items from json


I'm learning reason react and am having trouble rendering a list of items I'm fetching from a json api.

let url = region => {
  "https://api.openbrewerydb.org/breweries?by_state="
  ++ Js.String.replaceByRe([%re "/\\s/g"], "_", String.lowercase(region));
};

[@react.component]
let make = (~region) => {
  let (breweries, setBreweries) = React.useState(() => []);

  React.useEffect1(
    () => {
      Js.Promise.(
        Axios.get(url(region))
        |> then_(response => {
             resolve(setBreweries(response##data));
           })
      );
      None;
    },
    [|region|],
  );

  let renderBrewery = brw => <div> {ReasonReact.string(brw##name)} </div>;

  <div>
    {breweries |> List.map(renderBrewery) |> Array.of_list |> React.array}
  </div>;
};

I am getting back the data I expect in the then_ block. However, when the items are rendered I get a JS error saying TypeError: brw is undefined meaning that somewhere there is a discrepancy between the object I receive and the object I'm trying to render.


Solution

  • The problem is (almost certainly) that you're using List.map on an array.

    Lists and arrays are not the same. The array [|1, 2, 3|] will be represented as an ordinary array in JavaScript, but a list [1, 2, 3] will be represented as nested two-element arrays, [1, [2, [3, 0]]] , with each array (cons-cell) containing one element and a pointer to the next cell, or 0 as a terminator.

    List.map will continue to iterate until it encounters 0 as the second element of a cell, which of course it never does. Instead it continues to iterate on garbage data until it crashes.

    The solution should be as simple as replacing List.map with Array.map and removing Array.of_list since that's now unnecessary.

    It's also worth noting that this might have been prevented with type annotations, and almost certainly with JSON decoders. Having to spend time tracking down hard to catch errors like this is the price you pay for the convenience of dynamic typing.