UseEffect被多次调用

时间:2020-06-29 04:06:47

标签: javascript reactjs fetch fetch-api use-effect

我认为useeffect仅在渲染之后被调用一次,但是它被执行了多次,而不是按照我期望的顺序执行。我希望在进行提取的同时将其加载到味精“数据加载”中,然后完成提取后,渲染标题字段并一次警告“ ..Done ...”,那应该就此结束。 我在两点添加了ALERT和控制台日志来确定流量,并且警报和控制台日志都以不同的顺序出现多次。您能否运行此代码并查看其行为。我将第二个参数数组保留为null,以使其仅运行一次,但无济于事。

第二,请说明反应RENDER是否表示在屏幕上显示? LOAD指示哪个阶段?显示何时完成?

代码如下:

import React, { useEffect, useState } from "react";
//import "./App.css";

function DemoFetchZ() {
  let data = { title: "Waiting for Data" };
  const [todo, setTodo] = useState(data);
  const [isData, setData] = useState(false);
  const [isFetching, setFetching] = useState(false);

  useEffect(() => { // called after the first render
    async function fetchData() {
      setFetching(true);
      const response = await fetch(
        "https://jsonplaceholder.typicode.com/todos/1"
      );
      console.log("response = ", response);
      let data = await response.json();
      setTodo(data); //updt state
        setFetching(false);
        setData(true)
      console.log("Data = ", data);
    }
    fetchData();
  }, []); //[isData] null value will execute once only?

  if (isFetching) {
      console.log("data loading ......")
      alert ("data loading")
      return (<div>...Data Loading.....</div>);
  }

  return (
    <div>
           - Fetch
          <br /> {alert("..DONE...")}
      <span>Title: {todo.title}</span>
    </div>
  );
}

export default DemoFetchZ;

感谢您的帮助,

2 个答案:

答案 0 :(得分:6)

您的useEffect在每个渲染周期仅执行一次 ,但是您的useEffect中有多个状态更新会导致重新渲染。因此,您会收到很多警报。

See a demo of your code并查看console.log和注释

还请注意,useEffect

  • 当您提供空数组依赖项时,useEffect将执行一次
  • 当您将某个值作为依赖项时(例如[name]),您的useEffect在名称状态/属性更改时执行
  • 如果您不提供任何依赖,
  • useEffect将在每次重新渲染时执行。

Read here on re-render

答案 1 :(得分:2)

像这样重构它。

import React, { useEffect, useState } from "react";
//import "./App.css";

const DemoFetchZ = () => {
  const [todo, setTodo] = useState({});
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = () => {
    setLoading(true);
    fetch("https://jsonplaceholder.typicode.com/todos/1")
      .then((response) => response.json())
      .then((data) => {
        setTodo(data);
        setLoading(false);
      })
      .catch((error) => {
        console.log(error);
        setLoading(false);
      });
  };

  return (
    <>
      {loading ? (
        <div>...Data Loading.....</div>
      ) : (
        <div>
          - Fetch
          <br />
          <span>Title: {todo ? todo.title : "no Title Found"}</span>
        </div>
      )}
    </>
  );
};

export default DemoFetchZ;