繁体   English   中英

UseEffect 被多次调用

[英]UseEffect being called multiple times

我认为useEffect仅在渲染后调用一次,但它被执行多次,而不是按我预期的顺序执行。

我希望它在提取过程中发送消息“数据加载”,然后一旦完成提取,呈现标题字段并警告“..Done ...”一次,这应该是结束。

我在这两个点添加了 ALERT 和控制台日志以确定流程,并且警报和控制台日志都以不同的顺序出现不止一次。 您能否运行此代码并查看行为。 我将第二个参数数组保留为 null 以使其仅运行一次但无济于事。

请澄清反应渲染是否意味着在屏幕上显示? 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;

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

查看您的代码演示并查看 console.logs 以及注释

还要注意useEffect

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

在此处阅读重新渲染

像这样重构它。

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;

对于未来的读者。

React 18 为严格模式引入了新的仅开发检查。 每当第一次安装组件时,此新检查将自动卸载并重新安装每个组件,在第二次安装时恢复以前的 state。

在这种情况下,useEffect 回调会为初始渲染运行两次。 state 更改后,组件渲染两次,但效果应该运行一次。

阅读此链接了解更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM