如何在没有 useEffect 的情况下在 React 组件中使用异步等待

How to use async await in React components without useEffect

我的应用程序有一个搜索栏,用户可以在其中输入单词并单击搜索。单击后,应用程序会从打开的词典 API 中获取该词的定义,然后更新父组件的状态以反映结果。然后该组件应该通过将结果作为道具传递给展示性子组件来呈现结果。

但是,状态似乎在获取调用有时间 return 数据之前就已设置。所以直到再次点击搜索按钮才会呈现搜索结果,造成混乱。

我尝试通过使我的函数异步来解决这个问题(Dictionary.search 指的是一个处理获取的导入函数,returns 是数组形式的结果):

async search(term) {
    const results = await Dictionary.search(term);
    this.setState({ searchTerm: term, results: results });
  }

然而,这只在某些时候有效。对于较长的搜索,它不会等待更新状态和重新呈现。

我进行了一些谷歌搜索,发现了这个建议,但它也不起作用:

search = (term) => {
    const dictionarySearch = async (term) => {
      const results = await Dictionary.search(term);
      this.setState({ searchTerm: term, results: results });
    };
    dictionarySearch(term);
};

编辑添加:这是 Dictionary.search 代码及其辅助函数:

//Create an empty array in which the results of the API call will be stored
let results = [];

const Dictionary = {
  search(term) {
    //Url with our search term and API key:
    const url = `https://www.dictionaryapi.com/api/v3/references/collegiate/json/${term}?key=${api_key}`;

    //Fetch the results from Merriam Webster API:
    fetch(url)
      .then((response) => {
        //Catch an error from their server
        if (!response.ok) {
          throw new Error("Network response was not ok");
        }
        //Return javaScript object version of the response
        return response.json();
      })
      .then((jsonResponse) => {
        //Perform the helper function on the javascript object and return the result (array)
        return shortDef(jsonResponse);
      })
      //Catch any other errors than a server error
      .catch((error) => {
        console.error(
          "There has been a problem with your fetch operation:",
          error
        );
      });

    //Create a copy of the results array
    let returnResults = results.slice();
    //Reset the original array to an empty array
    results = [];
    //Return the copy
    return returnResults;
  },
};

//Helper function to extract only certain info from the API
function shortDef(response) {
  response.forEach((object) => {
    //Create a new object for each object int he response array
    let result = { word: "", type: "", definitions: [] };
    //Add the word and type to the object
    result.word = object.hwi.hw;
    result.type = object.fl;
    //Add the definitions to the object. There may be several, so it is pushed to an array.
    let defs = object.shortdef;
    defs.forEach((def) => {
      result.definitions.push(def);
    });

    //Add the object to the array of API results
    results.push(result);
  });
  //Return the list of results
  return results;
}

我不想在 ComponentDidMount 中调用 API,因为每次用户按下“搜索”时它都应该被调用。我也不想使用 useEffect,因为这意味着将我的整个组件从 class 重构为一个函数。

有没有办法让 class 组件中的 setState 等待异步任务完成?

问题是您的 Dictionary.search 函数立即 returns,因为它没有等到 .then 块解析。将其更改为 async 函数和 await urlfetch。它应该是这样的:

const Dictionary = {
  // Make search an async function
  search: async term => {
    const url = `https://www.dictionaryapi.com/api/v3/references/collegiate/json/${term}?key=${api_key}`;

    // Await the results
    await fetch(url)
      .then(response => {
        // ...
      })
      .then(jsonResponse => {
        // ...
      })
      .catch(error => {
        // ...
      });

    return;
  },
};