变量在获取时已更改,但在函数外部未更改

时间:2019-07-22 05:04:22

标签: javascript reactjs typescript fetch-api

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

我已经在onload函数(我的提取位于其中)的外部声明了变量,并在提取中为其分配了不同的值。它们的变量将在获取时更改,但在获取之外它们将保持不变。

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

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

我也尝试过将获取操作放到其他组件中(如下面的表格所示),但是随后我必须声明两个状态并在获取操作中调用获取操作,因为我已经在此处调用了另一个获取操作,并且变得麻烦...

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。返回正确的值后,我希望将它们作为道具传递给组件。

非常感谢!

3 个答案:

答案 0 :(得分:1)

部分问题是您似乎无法正确地区分同步代码和异步代码。 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),以了解您可以遵循的内容以及是否有什么可以跳过的内容。您需要熟悉一些东西。

答案 1 :(得分:0)

请尝试使用状态变量,因为如果状态变量更改,则渲染将再次调用,此处您使用的普通变量可能是其更改但不是渲染。

谢谢。

答案 2 :(得分:0)

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