首页 > 解决方案 > 使用 UseEffect 从 API 获取数据

问题描述

我找到了一个返回单词定义的 API。

我想显示一个单词和定义,当按下按钮时它应该重新获取并显示新单词。

我写了这段代码。但我不能让它工作。我不确定我做错了什么。

我不想使用 Axios 或任何库

import React, { useEffect, useState, Button } from "react";

function RandomWord() {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  const [refetch, setRefetch] = useState(false);

  useEffect(() => {
    fetch("https://rnd-word.vercel.app/word")
      .then((response) => response.json())
      .then((json) => setData(json))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, [refetch]);

  return (
    <>
      <div class="App">
        {isLoading ? (
          <p>Loading...</p>
        ) : (
          <span
            data={data}
            keyExtractor={({ id }, index) => id}
            renderItem={({ item }) =>
            <p>{item.word}</p>
            <p>{item.defintion}</p>
          }
          />
        )}
      </div>
      <Button
        title="New Word"
        onPress={() => setRefetch(!refetch)}
        color="#e56b6f"
      />
    </>
  );
}

export default RandomWord;

标签: reactjs

解决方案


<span>html 元素没有类似renderItemor的属性keyExtractor。当你想要渲染时,data你应该将它映射到 JSX。

data.map((item, index) => 
  <div key={index}>
      <p>{item.word}</p>
      <p>{item.definition}</p>
  </div>

您也可以直接调用获取数据的函数,而不必触发另一个仅触发获取的重新渲染。

function fetchNextWord(){
  setLoading(true);
  fetch("https://rnd-word.vercel.app/word")
    .then((response) => response.json())
    .then((json) => setData(json))
    .catch((error) => console.error(error))
    .finally(() => setLoading(false));
}

useEffect(fetchNextWord, []); // Initial load

您可以运行此示例代码段:

const { useState, useEffect } = React;

function RandomWord() {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  
  function fetchNextWord(){
    setLoading(true);
    fetch("https://rnd-word.vercel.app/word")
      .then((response) => response.json())
      .then((json) => setData(json))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }
  
  useEffect(fetchNextWord, []); // Initial load


  return (
    <div>
      <div className="App">
        {isLoading ? (
          <p>Loading...</p>
        ) : 
          data.map((item, index) => 
           <div key={index}>
               <p>{item.word}</p>
               <p>{item.definition}</p>
           </div>
          )
        }
      </div>
      <button
        onClick={fetchNextWord}
        color="#e56b6f"
        >New Word</button>
    </div>
  );
}

ReactDOM.render(<RandomWord />, document.getElementById("root"));
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读