0

我正在进行 API 调用,并成功更新了状态。API 中的数据如下所示:

{ 
 "data": [{"name": string}, {"name":string}, ...]
}

didMount我正在我的生命周期方法中制作 API 。只是为了测试,我使用onClick按钮上的 a 记录状态。当我有这样的日志记录语句Js.log(self.state.projects[0);时,数组中的第一个对象会像这样记录:

{ name: "Flaherty" }

name然后我像这样登录属性Js.log(self.state.projects[0].name。我希望"Flaherty"被记录,但只会undefined被记录。

我也尝试过name像这样从状态渲染:<div>(ReasonReact.stringToElement(self.state.projects[0].name)</div>我得到了这个神秘的错误:Cannot read property '__reactInternalInstance$fljwvs5b8u5' of null。我认为是由于状态不一致

我可以在反应开发工具中检查状态确实已经更新。我很困惑为什么我无法访问name. state.projects[0]请告知是否有人有线索!

我是 ReasonReact 的新手,也许我正在进行 API 调用并以最佳方式更新状态。如果有人对更好的方式有任何建议 - 我欢迎您的反馈。谢谢。

这是我的组件的样子:

type project = {
  name: string
};

type state = {
  projects: array(project)
};

type action =
  | FetchData(array(project))
  | Search;

let component = ReasonReact.reducerComponent("Projects");
let make = (_children) => {
  ...component,
  initialState: () => {
    projects: [||]
  },
  reducer: (action, _state) =>
    switch(action) {
    | FetchData(data) => ReasonReact.Update({projects: data})
    | Search => ReasonReact.NoUpdate
    },
  didMount: (self) => {
    Js.Promise.(
        Axios.get("/api/projects")
        |> then_((response) => resolve(self.send(FetchData(response##data))))
        |> ignore
    );
    ReasonReact.NoUpdate;
  },
  render: (self) =>
    <div>
      <div>
        <span>(ReasonReact.stringToElement("SEARCH"))</span>
        <input _type="text"/>
      </div>
      <div>
        <button onClick=((_) => Js.log(self.state.projects[0].name))>(ReasonReact.stringToElement("log data"))</button>
      </div>
      <div>
        (ReasonReact.arrayToElement(
          Array.mapi((i, project) => {
            <div key=string_of_int(i) >(ReasonReact.stringToElement(project.name))</div>
          }, self.state.projects)
        ))
      </div>
    </div>
};
4

2 回答 2

2

感谢@rickyvetter 花时间帮助并与我一起解决这个问题,问题被确定为来自 API 的数据的类型定义。与其定义为记录,不如将其定义为 javascript 对象,如下所示:

type project = {
  .
  "name": string
};

属性名称周围的字符串是sugar

然后应该使用js 对象访问器而不是使用点表示法。像这样:

self.send.projects[0]##name
于 2018-04-09T20:13:33.403 回答
2

问题是类型不兼容。

type project = {
  name: string
};

是记录类型,API 提供给您的数据是不兼容的 JS 对象:

{"name": string}

AxiosAPI 为您提供了一个形状未知的 JS 对象,并且在这一行:

|> then_((response) => resolve(self.send(FetchData(response##data))))

原因是推断 response##data 是一个记录数组,而不是它真正的对象数组。这可以通过更改类型来解决project

type project = {.
  "name": string
};

表示它实际上是一个 JS 对象,或者通过从 api 响应转换为记录,例如:

let projObjToRecord = projObj => {name: projObj##name};

并映射对象以转换它们。如果您选择前者,那么您还必须更新调用站点以使用##而不是.访问。

于 2018-04-09T20:15:03.737 回答