【问题标题】:Variables Being Changed In Fetch But Unchanged Outside of Function变量在 Fetch 中被改变但在函数之外没有改变
【发布时间】:2019-11-30 01:00:33
【问题描述】:

我有一个 React 应用程序,我有一个应用程序容器,我想在其中调用 fetch 以获取一些数据以传递给需要该信息的组件。

我在 onload 函数(我的 fetch 所在的位置)之外声明了变量,并在 fetch 中为它们分配了不同的值。它们的变量将在 fetch 中发生变化,但在 fetch 之外它们保持不变。

为什么他们没有保持改变,有没有办法解决这个问题?

我尝试更改使用 var 而不是 let 声明的变量,并且尝试将函数放在 const 中。

我也尝试将 fetch 放在其他组件中(如下所示的 Table),但是我必须声明两个状态并在 fetch 中调用 fetch,因为我已经在那里调用了另一个 fetch 并且它变得很麻烦...

let latestRelease = 0;
let draftRelease = 0;
let doClone = false;

function onload() {

  fetch(url, {
    method: 'GET'
  })
    .then(function(response) {
      return response.json();
    })
    .then(function(result) {
      for(var i = 0; i < result.length; i++)
      {
        if(result[i].id > latestRelease && result[i].status === "released") {
          latestRelease = result[i].id;
        }

        if(result[i].id > draftRelease && result[i].status === "draft") {
          draftRelease = result[i].id;
        }
      }

      if(latestRelease > draftRelease) {
        doClone = true;
      }
    })
    .catch((error) => {
      console.log(error);
    });
}

const App: React.FC = () => {
onload()
  return (
    <React.Fragment>
      <CssBaseline />
      <Container fixed>
        <PersistentDrawerLeft/>
        {console.log(latestRelease)} //displays 0
                <Title/>
          <Table />
      </Container>
    </React.Fragment>
  );
}

export default App;

我希望 latestRelease 和 draftRelease 不会保持为 0,而是大于 0,但输出仅为 0。返回正确的值后,我希望将它们作为 props 传递给组件。

非常感谢!

【问题讨论】:

  • 你的 onload 函数调用了什么?
  • @ZaidCrouch 啊!到目前为止什么都没有,但是如果我在 return() 之前调用它,它不会改变 console.log(latestRelease) 的输出

标签: javascript reactjs typescript fetch-api


【解决方案1】:

你能用状态变量试试吗,因为如果状态变量改变了渲染会再次调用,这里你使用一个普通的变量可能是它的改变但它不渲染。

谢谢。

【讨论】:

  • 嗨 ND NAVEEN,你是这个意思吗? reactjs.org/docs/hooks-state.html我不想显示我从 fetch 中获得的详细信息,所以我还需要 state 变量吗?
  • yes myrmidon999 ,状态变量的特性是当你改变状态变量时,它会自动调用功能组件中的返回或调用组件中的渲染。
【解决方案2】:

部分问题在于您似乎没有正确区分同步代码和异步代码。 fetch 是异步的,这意味着不能保证该代码在文件中的任何其他内容之前运行。 (fetch 使用 JS promises 来管理异步数据,所以对 using promises 有一个很好的把握。)

在典型的 React 案例中,您希望做一些不同的事情。首先,您希望使用组件状态来保存数据,而不仅仅是随机变量(这允许 React 在这些值发生变化时重新渲染)。其次,当您异步获取数据时,您需要在获取完成之前确定您的应用应该做什么。

这是一个非常基本的示例,展示了它是如何工作的:

import React, { useState, useEffect } from 'react'

const App = ({ url }) => {
  // We'll use this variable to store an object with the details
  const [releaseDetails, setReleaseDetails] = useState(null)

  // When the component is loaded, we'll fetch the url (coming from the component props) and then
  // run your logic.
  useEffect(() => {
    let latestRelease = 0;
    let draftRelease = 0;
    let doClone = false;

    fetch(url)
      .then((response) => response.json())
      .then((result) => {
        for(var i = 0; i < result.length; i++) {
          if(result[i].id > latestRelease && result[i].status === "released") {
            latestRelease = result[i].id;
          }

          if(result[i].id > draftRelease && result[i].status === "draft") {
            draftRelease = result[i].id;
          }
        }

        if(latestRelease > draftRelease) {
          doClone = true;
        }

        // To make these details available to the component, we'll bundle them into an object
        // and update the component's state:
        setReleaseDetails({
          latestRelease,
          draftRelease,
          doClone
        })
      })
      .catch((error) => {
        // You'd ideally want some proper error handling here
        console.log(error)
      });
  }, []) // pass an empty array so this is only run when the component is first rendered

  // Because we're getting the data asynchronously, we need to display something while we wait
  if(releaseDetails === null) {
    return "loading..."
  }

  // Once the data is available, you can then use the details when rendering. You could instead
  // render a child component and pass the values as props to it.
  return (
    `LatestRelease: ${releaseDetails.latestRelease}`
  )
}

一般来说,您可能需要确保掌握一些 React 和通用 JS 概念,尤其是在状态和异步数据获取方面。不确定到目前为止你有多少经验,但你可能想看看一些介绍性教程(可能像this official one),看看你可以遵循多少,以及是否有任何东西可以作为你的东西跳出来需要熟悉更多。

【讨论】:

  • 感谢您的回答,扎伊德!不幸的是,我不得不在没有完全理解它们是如何工作的情况下快速学习和使用东西。即使我不想显示我正在获取的数据,我仍然必须将它们存储在一个状态中,如果它们改变了 React 仍然需要重新渲染?
  • 为了清楚起见,重新渲染是您想要发生的事情,因为 React 如何更新以显示对其数据的任何更改(这里的主要情况是当获取完成并且数据可用时)。问题不在于您是否要显示数据,而在于您是否希望您的应用程序对这些数据执行某些操作——无论是将其显示在屏幕上还是将其作为道具传递给子组件。只要您确实想使用该数据,并且它可以更改(甚至从未提取到已提取),您就需要某种状态
  • 啊,好吧!这样就更清楚了,谢谢。但是,使用您的代码并仍然呈现我作为回报的子组件会出现“'latestRelease' 在类型'(prevState:null)=> null'中不存在”。错误?我认为这与开头声明的 const 变量有关。 null值可以改成any吗?
  • 对不起,应该特别提到我的答案是 js 而不是打字稿。它可能需要一些调整才能正常工作(这看起来确实是一个 ts 错误),但我不太熟悉,所以不能给你一个好的答案,抱歉:(
【解决方案3】:

变量应该处于重新渲染的状态

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    相关资源
    最近更新 更多