【发布时间】:2021-10-09 14:48:59
【问题描述】:
我的应用程序有一个搜索栏,用户在其中输入一个单词并点击搜索。单击后,应用程序会从打开的字典 API 中获取该单词的定义,然后更新父组件的状态以反映结果。然后,组件应该通过将结果作为 prop 传递给展示性子组件来呈现结果。
但是,状态似乎在 fetch 调用有时间返回数据之前就设置好了。所以直到再次点击搜索按钮才呈现搜索结果,造成混乱。
我已经尝试通过使我的函数异步来解决这个问题(Dictionary.search 指的是一个处理提取并以数组形式返回结果的导入函数):
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,因为这意味着将我的整个组件从一个类重构为一个函数。
有没有办法让类组件中的 setState 等待异步任务完成?
【问题讨论】:
-
您还应该显示您的
Dictionary.search。如果您像这样使用await,则无法“在 fetch 调用有时间返回数据之前设置状态”... -
很可能
Dictionary.search没有返回承诺……但你没有提供minimal reproducible example -
谢谢,我已经添加了。它不返回一个承诺,它返回一个数组。如果我让它返回一个 Promise,我是否应该尝试在我的组件中调用 shortDef 函数,将 Promise 转换为数组,而不是在 Dictionary.search 函数中?
标签: javascript reactjs async-await es6-promise