如何在没有 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
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;
},
};
我的应用程序有一个搜索栏,用户可以在其中输入单词并单击搜索。单击后,应用程序会从打开的词典 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
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;
},
};