The record field name can't be found

reasonreact
bsb

#1

Im getting this error

The record field name can't be found.
[0]
[0]   If it's defined in another module or file, bring it into scope by:
[0]   - Annotating it with said module name: let baby = {MyModule.age: 3}
[0]   - Or specifying its type: let baby: MyModule.person = {age: 3}

Here’s my file read.re


let str = ReasonReact.string;

let url = "http://localhost:3000/users";

type users = list(Data.user);

type user = Data.user;

type state =
  | Loading
  | Failure
  | Success(list(Data.user));

type action =
  | LoadUsers
  | Resolve(option(list(Data.user)));

let component = ReasonReact.reducerComponent("Read");

let make = _children => {
  ...component,
  initialState: () => Loading,
  reducer: (action, _state) =>
    switch (action) {
    | LoadUsers =>
      ReasonReact.UpdateWithSideEffects(
        Loading,
        (
          self =>
            Data.fetchUsers(url, payload => self.send(Resolve(payload)))
            |> ignore
        ),
      )
    | Resolve(result) =>
      switch (result) {
      | Some(users) => ReasonReact.Update(Success(users))
      | None => ReasonReact.Update(Failure)
      }
    },
  didMount: self => self.send(LoadUsers),
  render: self =>
    switch (self.state) {
    | Loading => <div> {str("Loading...")} </div>
    | Failure => <div> {str("Something went wrong!")} </div>
    | Success(users) =>
      <div>
        <h2> {str("Users")} </h2>
        <ul>
          {
            users
            |> List.map(user => <div> <li> {str(user.name)} </li> </div>)
            |> Array.of_list
            |> ReasonReact.array
          }
        </ul>
      </div>
    },
};

let default = ReasonReact.wrapReasonForJs(~component, _jsProps => make([||]));

The localhost url (“http://localhost:3000/users”) returns a list of users eg

[
  {
    id: 1,
    name: "User A"
  },
  {
    id: 2,
    name: "User B"
  },
  {
    id: 3,
    name: "User C"
  }
];

The File I Use for the data fetching is Data.re


open Belt;

type user = {
  id: int,
  name: string,
};

module Decode = {
  let user = user =>
    Json.Decode.{
      id: field("id", int, user),
      name: field("name", string, user),
    };
  let users = json: list(user) => Json.Decode.list(user, json);
};

let fetchUsers = (url, callback) =>
  Js.Promise.(
    Fetch.fetch(url)
    |> then_(Fetch.Response.json)
    |> then_(json =>
         json
         |> Decode.users
         |> (
           users => {
             callback(Some(users));
             resolve();
           }
         )
       )
    |> catch(_err => {
         callback(None);
         resolve();
       })
  );

Here’s a picture of the terminal message

image

is there something I’m missing


#2

Try

users
            |> List.map(user => <div> <li> {str(user.Data.name)} </li> </div>)

#3

You can try it:

users
|> List.map(user => <div> <li> {str(user.Data.name)} </li> </div>)

or

users
|> List.map((user: Data.user) => <div> <li> {str(user.name)} </li> </div>)

or

users->Belt.List.map(user => <div> <li> {str(user.name)} </li> </div>)

The last shape (with belt) allows to use the inference of type.