#reactjs #react-hooks
#reactjs #реагирующие перехваты
Вопрос:
В react Hooks я пытаюсь извлечь данные из массива API, но в функции Foreach вызов API вызывает бесконечность. Как это исправить?
const [symbols, setSymbols] = useState([]);
getPortfolioSymbolList(portfolio_name).then(data => data.json()).then(res => {
res.forEach((symbol_data)=>{
fetchPrice(symbol_data.symbol).then(price => {
setSymbols(price);
});
})
}
function fetchPrice(symbol){
const price = fetch(`api_url`)
.then(chart => chart.json())
return price;
}
Здесь вызов fetchPrice() приводит к бесконечности.
Ответ №1:
Установка состояния всегда будет вызывать повторный запуск
В вашем коде выполняется запрос, а затем устанавливаются данные, вызывающие повторный запрос. Затем из-за повторной отправки запрос выполняется снова и снова устанавливает состояние и снова вызывает повторную отправку.
Если у вас есть запрос на данные, вы, вероятно, захотите указать React.useEffect
, чтобы он запрашивал только один раз.
React.useEffect(() => {
/* your data request and data set */
}, []); // the [] will only fire on mount.
Ответ №2:
Это связано с тем, что ваш setSymbols
вызов внутри forEach вызывает перезапуск компонента (перезагрузку) — это означает, что вся ваша основная функция компонента вызывается снова и снова… getPortfolioSymbolList
тоже. Вы должны использовать useEffect
перехват для решения этой проблемы. Ваш вызов API getPortfolioSymbolList() должен находиться внутри useEffect.
Ответ №3:
ПРОБЛЕМА
Ваш первый символ обновляется в вашем вызове API, что запускает повторный рендеринг компонента, вызывающего вызов API, для перехода в бесконечный цикл.
РЕШЕНИЕ
- Оберните свой
API
в свойuseEffect
. Функция внутри вашего useEffect будет вызвана только один раз. Смотрите Документы useEffect здесь - Вам нужно использовать
for await of
для асинхронного цикла.forEach
не удается выполнить асинхронный цикл. Смотритеfor await of
Документы здесь - Обновите свои символы, как только все данные будут собраны.
function Symbols() {
const [symbols, setSymbols] = useState([]);
React.useEffect(() => {
async function fetchSymbols() {
const portfolio = await getPortfolioSymbolList(portfolio_name);
const jsonPortfolios = await data.json();
const symbols = [];
for await (let jsonPortfolio of jsonPortfolios) {
const price = await fetchPrice(jsonPortfolio.symbol);
symbols.push(price);
}
setSymbols(symbols);
}
fetchSymbols();
}, []);
return /** JSX **/
}