ReasonReact useState с извлеченными данными - PullRequest
1 голос
/ 24 июня 2019

Я давно пользуюсь React, и я хотел бы дать шанс Reason React. Затем я создал небольшой проект для извлечения данных из хранилища Github и отображения результатов.

Я хотел бы использовать React Hooks и сохранить результаты в моем состоянии.

Вот что я пытаюсь сделать:

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);
};

при попытке сделать setResult(_ => decodedRepo) выдает ошибку

Это имеет тип: githubRepo Но где-то хотел: list ('a)

Я знаю, что инициализировал свой React.useState пустым списком, но я не могу понять, как установить decodedRepo внутри.

Вот результат Js.log(decodedRepo):

Array [ "Node.js", "https://api.github.com/orgs/nodejs" ]
  0: "Node.js"
  1: "https://api.github.com/orgs/nodejs"
  length: 2

Я также хотел бы знать, есть ли способ инициализации useState без значения?

1 Ответ

3 голосов
/ 25 июня 2019

Вы можете добавить элемент к списку, используя синтаксис распространения списка , так же, как в JavaScript:

setResult(result => [decodedRepo, ...result]);

Но если вы не хотите иметь дело с возможностью более одного предмета, вам нужно использовать контейнер, который ограничен либо нулем, либо только одним предметом. Это тип option . При использовании это будет выглядеть примерно так:

let (result, setResult) = React.useState(() => None);
setResult(result => Some(decodedRepo));

Тогда, когда вы используете result, вы вынуждены иметь дело с возможностью того, что он может содержать или не содержать элемент:

switch (result) {
| Some(decodedRepo) => ...
| None => ...
}
...