useEffect 渲染后不运行

Hoa*_*gdz 4 async-await reactjs react-hooks use-effect use-state

我对 useEffect 是如何触发的以及它是如何工作的感到有点困惑。我写了一个这样的函数,但 useEffect 根本不运行。我想从API获取数据,然后根据数据渲染页面。但它不会触发 useEffect。如果我不使用 useEffect,它将渲染页面三次。

async function getData() {
  var tmpArrData = [];
  await fetch("this API is hidden due to the privacy of the company - sorry")
    .then((res) => res.json())
    .then((data) => {
      console.log("data", data);
      tmpArrData = data;
  });
  console.log("tmpData ", tmpArrData);
  return tmpArrData;
}

function App() {

  const [arrData, setArrData] = useState();
  const [loadData, setLoadData] = useState(false);

  useEffect(() => {
    console.log("if it works, this line should be shown");
    const tmpArrData = getData();
    setArrData(tmpArrData);
  }, [arrData]);


  const data = arrData[0];
  console.log(data);

  return (
      <GifCompoment 
      id = {data.id}
      name = {data.name}
      activeTimeTo = {data.activeTimeTo}
      activeTimeFrom = {data.activeTimeFrom}
      requiredPoints = {data.requiredPoints}
      imageUrl = {data.imageUrl}
      />
  );
}

export default App;

Run Code Online (Sandbox Code Playgroud)

Dre*_*ese 5

useEffect钩子保证在初始渲染结束时至少运行一次。

getData是一个async函数,useEffect回调代码不等待它解析。简单的解决方案是从隐式返回的 Promise 进行链接getData并访问解析值以更新arrData状态。确保从useEffect的依赖数组中删除状态,这样就不会创建渲染循环。

getData只需返回结果即可清理/加强实现,fetch无需先保存到临时变量中。

async function getData() {
  return await fetch(".....")
    .then((res) => res.json());
}

useEffect(() => {
  console.log("if it works, this line should be shown");
  getData().then((data) => {
    setArrData(data);
  });
}, []); // <-- empty dependency so effect called once on mount
Run Code Online (Sandbox Code Playgroud)

此外,由于arrData最初未定义,arrData[0]因此可能会引发错误。您可能需要提供有效的初始状态,并在第一个元素未定义时提供后备值,这样您就不会尝试访问未定义对象的属性。

const [arrData, setArrData] = useState([]);
Run Code Online (Sandbox Code Playgroud)

...

const data = arrData[0] || {}; // data is at least an object

return (
  <GifCompoment 
    id={data.id}
    name={data.name}
    activeTimeTo={data.activeTimeTo}
    activeTimeFrom={data.activeTimeFrom}
    requiredPoints={data.requiredPoints}
    imageUrl={data.imageUrl}
  />
);
Run Code Online (Sandbox Code Playgroud)