I'm using useState to store the data returned from an api:
function App() {
const [{ ipAddressData, shouldLoadItems }, setModel] = useState<AppState>({
ipAddressData: [],
shouldLoadItems: true,
});
const [ipAddress, setIpAddress] = useState("");
const ipDataUrl = `https://geo.ipify.org/${ipAddress}`;
useEffect(() => {
const fetchData = async () => {
const response = await fetch(ipDataUrl);
const data: IpAddress[] = await response.json();
setModel({
ipAddressData: data,
shouldLoadItems: false,
});
};
if (shouldLoadItems) {
fetchData();
}
}, [shouldLoadItems]);
function inputIp(e: { preventDefault: () => void }) {
setModel((prevState) => {
return {
...prevState,
shouldLoadItems: true,
};
});
e.preventDefault();
}
Then i'm trying to return the data but i get the following error: Uncaught TypeError: Cannot read properties of undefined
const { ip, location, domains, as, isp }: IpAddressData = ipAddressData;
return (
<div className="App">
<main className={mainCss}>
<h1 className={mainTitleCss}>IP Address Tracker</h1>
<form className={searchBarContainerCss} onSubmit={inputIp}>
<input
type="text"
placeholder="Search for any IP address or domain"
className={searchInputCss}
onChange={(e) => setIpAddress(e.target.value)}
/>
<input type="submit" value="" className={searchBarButtonCss} />
</form>
<Results
ip={ip}
location={getLocation(
location.city,
location.country,
location.postalCode
)}
timezone={location.timezone}
isp={isp}
/>
function getLocation(city: string, country: string, postalCode: string) {
return `${city}, ${country} ${postalCode}`;
}
Results.tsx:
interface IpAddressProps {
ip: string;
location: string;
timezone: string;
isp: string;
}
const Results: FC<IpAddressProps> = ({ ip, location, timezone, isp }) => {
return (
<div className={resultsContainerCss}>
<div className={resultCss}>
<div className={resultTitleCss}>IP Address</div>
<div className={resultInfoCss}>{ip}</div>
</div>
<div className={resultCss}>
<div className={resultTitleCss}>Location</div>
<div className={resultInfoCss}>{location}</div>
</div>
<div className={resultCss}>
<div className={resultTitleCss}>Timezone</div>
<div className={resultInfoCss}>UTC {timezone}</div>
</div>
<div className={resultCss}>
<div className={resultTitleCss}>ISP</div>
<div className={resultInfoCss}>{isp}</div>
</div>
</div>
);
};
export default Results;
index.ts where my interfaces are stored:
interface Location {
country: string;
region: string;
city: string;
lat: number;
lng: number;
postalCode: string;
timezone: string;
geonameId: number;
}
interface As {
asn: number;
name: string;
route: string;
domain: string;
type: string;
}
export interface IpAddressData {
ip: string;
location: Location;
domains: string[];
as: As;
isp: string;
}
export interface IpAddress {
data: IpAddressData;
}
When i console.log ipAddressData it returns the data from the api as expected so i don't know what the problem is
I found the error, AppState
interface had ipAddressData
defined as an array when in reality it should be an object and that was the reason it was returning undefined.
interface AppState {
ipAddressData: IpAddressData[];
shouldLoadItems: boolean;
}
Should be this instead:
interface AppState {
ipAddress: IpAddress | undefined;
shouldLoadItems: boolean;
}