javascript - React 中状态变量的顺序重要吗?

当我执行下面的代码时出现错误“无法读取 null 的属性(读取‘登录’)”,因为它到达了最后的 return 语句,它不应该因为我在返回之前已经检查了 bool 值.

import React, { useState, useEffect } from 'react';
const url = 'https://api.github.com/users/QuincyLarsn';
const MultipleReturns = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [isError, setIsError] = useState(false);
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(data => {
        if (data.status >= 200 && data.status <= 299)
          return data.json();
        else {
          console.log("here");
          setIsLoading(false);
          setIsError(true);
          console.log("here 2");
        }
      })
      .then(result => {
        setIsLoading(false);
        setUser(result);
      })
      .catch(error => console.log(error))
  }, []);

  console.log(isError);
  if (isLoading)
    return <h2>Loading...</h2>
  if (isError) {
    return <h2>Error...</h2>
  }

  return <h2>{user.login}</h2>

};

export default MultipleReturns;

在上面的代码中,如果 setIsError(true) 放在 useEffect 中的 setIsLoading(false) 之前,那么一切正常,反之亦然,类似地,如果 url 是正确的,那么如果 setUser(result) 放在之前,一切都正常setIsLoading(false) 而不是相反。 我无法弄清楚为什么会这样。

最佳答案

React 不会从 fetch() 批处理状态更新。在事件监听器的情况下,它是批处理的。这是一个异步获取调用。

在此sandbox控制台,您可以看到在状态更新之间有一个渲染 - setIsLoading(false)setIsError(true)

因此对于一个渲染周期:isLoading 为 false 并且 isError 也为 false。这将导致错误情况。

您可以使用 unstable_batchedUpdates 来强制执行批处理。

import { useEffect, useState } from "react";
import { unstable_batchedUpdates } from "react-dom";
import "./styles.css";

const url = "https://api.github.com/users/QuincyLarsn";
const App = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [isError, setIsError] = useState(false);
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetch(url)
      .then((data) => {
        if (data.status >= 200 && data.status <= 299) return data.json();
        else {
          console.log("here");
          unstable_batchedUpdates(() => {
            setIsLoading(false);
            setIsError(true);
          });
          console.log("here 2");
        }
      })
      .then((result) => {
        setIsLoading(false);
        setUser(result);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  console.log("isError", isError);
  if (isLoading) return <h2>Loading...</h2>;
  if (isError) return <h2>Error...</h2>;

  return <h2>{user.login}</h2>;
};

export default App;

Corrected Sandbox Link

https://stackoverflow.com/questions/70439180/

相关文章:

javascript - 数据到达 Controller 但不查看

c# - 检查ClassDeclarationSyntax是否实现了特定接口(interface)(

answer-set-programming - 使用答案集编程的 N 皇后问题

python - 如何在 ClientOSError : [Errno 104] Connectio

python - 将二元运算符添加到 z3

c# - 如何同步运行异步枚举器方法并将其存储为 IEnumerable?

python - 如何像在 C# 中一样同步运行 Python 协程,直到第一次等待?

yarnpkg - 无法使用 Yarn v.3 找到模块

c++ - 模板数据结构 - 访问从抽象类派生的模板类的 getter 和 setter

javascript - 如何制作一种类型取决于参数