問題:
我正在開發一個小應用程式,它是一級方程式賽車手的記憶游戲來練習 React。它呼叫 API 以獲取驅動程式資訊,然后我必須對 Wikipedia 進行第二次 API 呼叫以獲取驅動程式影像。當我提交年份并單擊按鈕時,它只會加載一半的資訊Image 1 & getDrivers function。當我再次單擊該按鈕時,它將加載影像Image 2 & getDriversImgs function / retrievingImgUrl。
我相信我遇到了一個 GOTCHA 或做一些根本錯誤的事情。我不確定在我的 setDrivers 呼叫中 retrievingImgUrl() 函式是否沒有更新,因為它是對陣列的參考,即使我使用 map 并且它應該回傳一個新陣列?
還是我需要使用 useEffect 或 useCallback 來一次性重新渲染代碼?
關于如何修復錯誤的任何建議,如果你能指出我可能清理這些 fetch 呼叫的方向,或者你會考慮這個干凈的代碼(比如在概念上將 fetch 呼叫鏈接到較小的函式中,還是應該把它變成一個大函式) ?
import { Fragment, useState, useEffect } from "react";
// Components
import Header from "./components/header/Header";
import CardList from "./components/main/CardList";
import Modal from "./components/UI/Modal";
// CSS
import classes from "./App.module.css";
function App() {
const [drivers, setDrivers] = useState([]);
const getDrivers = async (year) => {
const response = await fetch(
"https://ergast.com/api/f1/" year "/drivers.json"
);
const data = await response.json();
let driverInfo = [];
data.MRData.DriverTable.Drivers.map((driver) => {
driverInfo.push({
id: driver.code,
firstName: driver.givenName,
lastName: driver.familyName,
wikipedia: driver.url,
image: null,
});
});
setDrivers(driverInfo);
getDriversImgs();
};
async function getDriversImgs() {
console.log(drivers);
const responses = await Promise.all(
drivers.map((driver) => {
let wikiPageName = driver.wikipedia.split("/").slice(-1).toString();
let wiki_url =
"https://en.wikipedia.org/w/api.php?origin=*&action=query&titles="
wikiPageName
"&prop=pageimages&format=json&pithumbsize=500";
return fetch(wiki_url);
})
);
const urls = await Promise.all(responses.map((r) => r.json())).then(
(json) => retrievingImgUrl(json)
);
setDrivers((prev) => {
return prev.map((item, idx) => {
return { ...item, image: urls[idx] };
});
});
}
const retrievingImgUrl = async (data) => {
console.log(data);
const strippingData = data.map((d) => {
return d.query.pages;
});
const urls = strippingData.map((d) => {
const k = Object.keys(d)[0];
try {
return d[k].thumbnail.source;
} catch {
return null;
}
});
return urls;
};
return (
<Fragment>
<Header getDrivers={getDrivers} />
<CardList drivers={drivers} />
</Fragment>
);
}
export default App;
圖 1(單擊按鈕一次):

圖 2(單擊按鈕兩次):

Object20Object 錯誤:
const Header = (props) => {
const driverYear = useRef();
const driverYearHandler = (e) => {
e.preventDefault();
console.log(driverYear);
const year = driverYear.current.value;
console.log(typeof year);
props.getDrivers(year.toString());
};
return (
<header className={classes.header}>
<Title />
<form onSubmit={driverYearHandler}>
{/* <label htmlFor="year">Enter Year:</label> */}
<input
type="text"
id="year"
ref={driverYear}
placeholder="Enter Year:"
/>
<button onClick={props.getDrivers}>Get Drivers</button>
</form>
</header>
);
};
export default Header;
控制臺錯誤:

更新的 FETCH 呼叫
const getDrivers = async (year) => {
console.log("Running more than once??");
const url = "https://ergast.com/api/f1/" year "/drivers.json";
const response = await fetch(url);
const data = await response.json();
let driverInfo = [];
data.MRData.DriverTable.Drivers.map((driver) => {
driverInfo.push({
id: driver.code,
firstName: driver.givenName,
lastName: driver.familyName,
wikipedia: driver.url,
image: null,
});
});
getDriversImgs(driverInfo).then((data) => setDrivers(data));
console.log("Here is driver info", driverInfo);
};
const getDriversImgs = async (driverInfo) => {
const responses = await Promise.all(
driverInfo.map((driver) => {
let wikiPageName = driver.wikipedia.split("/").slice(-1).toString();
let wiki_url =
"https://en.wikipedia.org/w/api.php?origin=*&action=query&titles="
wikiPageName
"&prop=pageimages&format=json&pithumbsize=500";
return fetch(wiki_url);
})
);
const urls = await Promise.all(responses.map((r) => r.json())).then(
(json) => retrievingImgUrl(json)
);
return driverInfo.map((item, idx) => {
return { ...item, image: urls[idx] };
});
};
const retrievingImgUrl = async (data) => {
const strippingData = data.map((d) => {
return d.query.pages;
});
const urls = strippingData.map((d) => {
const k = Object.keys(d)[0];
try {
return d[k].thumbnail.source;
} catch {
return null;
}
});
return urls;
};
uj5u.com熱心網友回復:
這很可能是由于對setState. 您在呼叫getDriversImgs()之后setDrivers()呼叫,但任何設定狀態函式都是異步的。在您尋找驅動程式影像之前,它可能沒有完成設定。
在我看來,最簡單的解決方案是在您將setDrivers影像與每個驅動程式相關聯之前不要這樣做。您已經將所有內容driverInfo放在一個陣列中,因此遍歷該陣列并找到驅動程式的影像應該非常簡單。
創建包含driverInfo驅動程式影像的陣列后,您可以使用它將其渲染到 DOM。setDrivers
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/505404.html
標籤:javascript 反应
