我的应用程序有一个搜索栏,用户在其中输入一个单词并点击搜索。单击后,应用程序从开放的字典API中获取该词的定义,然后更新父组件的状态以反映结果。然后,该组件应该通过将结果作为道具传递给表示子组件来呈现结果。
然而,看起来状态在fetch调用有时间返回数据之前就已经设置好了。因此,直到再次单击搜索按钮才显示搜索结果,从而造成混乱。
我已经尝试通过使我的函数异步(字典)来解决这个问题。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);
};
编辑补充:这是词典。搜索代码及其辅助函数:
//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,因为它应该在每次用户按下"search"时被调用。我也不希望使用useEffect,因为这意味着要将整个组件从一个类重构为一个函数。
有没有办法让setState在类组件等待异步任务完成?
问题是您的Dictionary.search
函数立即返回,因为它不等待直到.then
块解析。将其改为async
功能,将await
改为url
的fetch
功能。它应该看起来像这样:
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;
},
};