reactjs JavaScript Axios GET响应未存储在全局变量中

kb5ga3dv  于 2023-04-20  发布在  React
关注(0)|答案(2)|浏览(135)

我试图将async/await函数中的API响应存储到响应全局变量中,该变量稍后将由App()访问,但我被提示代码下方显示的错误。

async function getAllTutors() {
    try{
        const response = await axios.get('API...');
        console.log("getAllTutors(): " + JSON.stringify(response.data.body));
        return response;
    }catch(error) {
        return [];
    }
    
}

var response = null;
(async () => {
    console.log("Retrieving Tutors");
    response = await getAllTutors();
    console.log("response (caller) = " +  JSON.stringify(response.data.body))
  })();

  
function App() {
...
    console.log("HERE: " + JSON.stringify(response.data.body));
    const [ data, setTutors ] = useState(employees);
...

error screenshot
我尝试在两个函数中记录值,它似乎确实输出了所需的JSON对象,但App()仍然显示未定义的响应变量。我甚至试图将App()更改为async/await,但我被引入其他错误。

n3schb8v

n3schb8v1#

所以response初始值为null。
你正在调用一些异步的函数,这些函数正在执行一些抓取操作。在某个时间点,这些函数将完成数据的抓取,并将response更新为该API的任何返回值。但是JS不想等待任何不需要的东西,除非你特别告诉它。所以当你深入到function App()时,即使该代码在其上面的所有逻辑之后出现,它也会在响应返回并更新'global'变量response之前立即执行。
本质上,由于JS的异步特性,在response被设置为API的响应之前,您正在调用response.data.body。这会出错,因为response为null。
你正在实现的模式是错误和奇怪的。响应可以存储在状态中,API调用可以在useEffect中执行,例如:

const [allTutors, setAllTutors] = useState(null);

useEffect(() => {
   const fetchData = async () => {
       const response = await getAllTutors();
       setAllTutors(response.data.body);
   }
   fetchData();
}, []);

或者类似于该结构的东西,可能会根据API返回的内容更改一些内容。

jqjz2hbq

jqjz2hbq2#

最简单的方法是存储一个promise,然后你可以在任何地方重用这个promise。
React中这种方法的问题在于它不是 * React式的 *;数据更改时不会触发任何重新渲染。
我建议使用上下文来 Package 任何需要数据的组件(或 Package 整个应用程序)。
举个例子

import { createContext, useContext, useEffect, useState } from "react";

const TutorsContext = createContext({ tutors: [] }); // default value

const getAllTutors = async () => (await axios.get("API...")).data.body;

// context provider
const TutorsProvider = ({ children }) => {
  const [tutors, setTutors] = useState([]);

  useEffect(() => {
    getAllTutors().then(setTutors).catch(console.error);
  }, []);

  return (
    <TutorsContext.Provider value={{ tutors }}>
      {children}
    </TutorsContext.Provider>
  );
};

// a handy hook
const useTutors = () => useContext(TutorsContext);

export { TutorsProvider, useTutors };

然后可以在提供程序中 Package 任何组件,例如

<TutorsProvider>
  <App />
</TutorsProvider>

在这些组成部分中

const { tutors } = useTutors();

这将确保在初始化上下文时只检索一次数据。然后可以与任何您想要的组件共享数据。

相关问题