使用React Hooks + Fetch API设置状态不会触发重新渲染

时间:2019-03-10 12:49:35

标签: reactjs fetch fetch-api

我试图通过构建一个简单的Domain Availability Checker学习React Hooks。具体来说,我正在玩useState()

目的只是要有一个输入字段,用户可以在其中输入关键字,然后按Enter,然后应用程序将对该关键字运行具有多个不同域名结尾的获取请求。

这是我的App组件(或在此处检查代码和框:https://codesandbox.io/s/5410rkrq1p

const App = () => {
  const domainEndings = [
    ".ws",
    ".ga",
    ".cf",
    ".tk",
    ".ml",
    ".gq",
    ".kz",
    ".st",
    ".fm",
    ".je"
  ];

  const [domainString, setDomainString] = useState("");
  const [domainsArray, setDomainsArray] = useState([]);
  const [lookedUpDomainsArray, setLookedUpDomainsArray] = useState([]);

  const handleDomainChange = event => {
    setDomainString(event.target.value);
    setDomainsArray(
      domainEndings.map(ending => event.target.value.trim() + ending)
    );
  };

  let testArray = [];

  const runDomainLookup = url => {
    return fetch(
      `https://domainr.p.rapidapi.com/v2/status?domain=${url}&mashape-key=${myAPIKEY}`
    )
      .then(res => res.json())
      .then(data => {
        testArray.push({
          url: data.status[0].domain,
          status: data.status[0].status
        });
        setLookedUpDomainsArray(testArray);
      });
  };

  const handleSubmit = e => {
    e.preventDefault();
    setLookedUpDomainsArray([]);
    testArray = [];
    domainsArray.map(eachDomain => runDomainLookup(eachDomain));
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          value={domainString}
          placeholder="type keyword then hit enter"
          onChange={e => handleDomainChange(e)}
        />
      </form>
      {lookedUpDomainsArray &&
        lookedUpDomainsArray.map((domain, index) => {
          return (
            <div key={index}>
              {domain.url} is {domain.status}
            </div>
          );
        })}
    </div>
  );
};

我遇到的错误是:

  • 状态似乎已正确设置(已在React Dev Tools中检查)。

  • 映射的提取请求中的第一个响应已正确呈现给DOM

  • 在用户按下输入字段中的键之前,不会触发针对新添加的状态(通过提取请求)的重新呈现

以下是演示它的视频:https://streamable.com/klshu

您会注意到,直到我开始在输入中输入其他字符后,其余结果才会出现

预先感谢

1 个答案:

答案 0 :(得分:0)

谢谢!是的,我尝试过Promise.all(),但是我希望每个获取请求都单独运行(例如,如果一个获取请求超时,则它将容纳所有其他请求)。

Reddit上找到了解决方案

基本上,当通过Hooks设置状态时,我应该这样传递以前的状态:

const runDomainLookup = url => {
    return fetch(
      `https://domainr.p.rapidapi.com/v2/status?domain=${url}&mashape-key=${myAPIKEY}`
    )
      .then(res => res.json())
      .then(data => {
        setLookedUpDomainsArray(prevArray => [
          ...prevArray,
          {
            url: data.status[0].domain,
            status: data.status[0].status
          }
        ]);
      });
  };

在CodeSandbox上有效的解决方案:https://codesandbox.io/s/51ky3r63x