I am trying to connect a test JSON server to my frontend react using axios. I see the objects in the Network inspect, but nothing displays to the site.
I'm thinking it may be something with the mapping? when I removed ? I get an error in the console. "Uncaught TypeError: Cannot read properties of undefined (reading 'map')" The status code reads 200 and I see the preview and response. I'm super new to Typescript and React so I'm not really sure what the issue is. Thanks for understanding!
testapi
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:3000/",
method: "GET",
});
useTest
import { CanceledError } from "axios";
import { useEffect, useState } from "react";
import testapi from "./api-client";
export interface Title {
title_id: number;
title_name: string;
title_description: string;
}
interface FetchTitleResponse {
count: number;
results: Title[];
}
const useTest = () => {
const [titles, setTitles] = useState<Title[]>([]);
const [error, setError] = useState("");
useEffect(() => {
const controller = new AbortController();
testapi
.get<FetchTitleResponse>("/titles", { signal: controller.signal })
.then((res) => setTitles(res.data.results))
.catch((err) => {
if (err instanceof CanceledError) return;
setError(err.message);
});
return () => controller.abort();
}, []);
return { titles, error };
};
export default useTest;
app
import useTest from "./useTest";
function App() {
const { titles, error } = useTest();
return (
<div>
{error && <div>{error}</div>}
hi
<ul>
{titles?.map((title) => (
<li key={title.title_id}>{title.title_name}</li>
))}
</ul>
</div>
);
}
export default App;
objects show in network preview, and heading is reading 200
response image, Note: on the JSON I changed the name from titles to results with no luck
Your code appears and runs correctly. Please make sure your response looks like this:
// where res.data =>
{
count: number,
results: [{
title_id: number,
title_name: string,
title_description: string
}]
}
In regards to the following line,
.then((res) => setTitles(res.data.results))
The res.data
is the complete response payload from GET request (an object). The subsequent access to results
(object array) is a named property of the response object.
Please review the example structure below. This is what the "Response" tab in Chrome should be displaying. It should not be a simple array of title objects.
// GET http://localhost:3000/titles (response)
{
"count": 2,
"results": [
{
"title_id": 1,
"title_name": "Foo",
"title_description": "Foo..."
},
{
"title_id": 2,
"title_name": "Bar",
"title_description": "Bar..."
}
]
}
The results
should not be null
. It looks like you are already guarding against null
with optional chaining:
<ul>
{titles?.map((title) => (
<li key={title.title_id}>{title.title_name}</li>
))}
</ul>
I suspect that your top-level results
key is not actually an array.