I'm trying to get a component (TestCard) to render the output of an API call I'm making with Axios. When I put the code of the TestCard component directly in the App() function of my App.js file, it renders as expected. But when I move this code out into its own function, it doesn't render the values. This is surprising to me, as I'm calling the same useState and useEffect functions to store the data from the API call in state.
I've listed the code below; what am I doing wrong here?
This is the code of the TestCard component:
function TestCard(props) {
return (
<Card sx={{ maxWidth: 345 }}>
<CardActionArea>
<CardMedia
component="img"
height="300"
image={props.preview_image}
alt={props.name} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{props.description}
</Typography>
<Typography variant="body2" color="text.secondary">
{props.description}
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
}
export default TestCard
This is the code directly in my App() function (this renders correctly):
function App() {
const [props, setProps] = useState({});
useEffect(() => {
axios.get(`http://localhost:9000/sessions/list`).then((row)=>setProps(row.data))
})
return (
<div>
<Card sx={{ maxWidth: 345 }}>
<CardActionArea>
<CardMedia
component="img"
height="300"
image={props.preview_image}
alt={props.name} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{props.description}
</Typography>
<Typography variant="body2" color="text.secondary">
{props.description}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</div>
);
}
export default App
And this is the imported function in my App() function (does not render the data correctly):
function App() {
const [props, setProps] = useState({});
useEffect(() => {
axios.get(`http://localhost:9000/sessions/list`).then((row)=>setProps(row.data))
})
return (
<div>
<TestCard name={props.name} description={props.description} preview_image={props.preview_image} />
</div>
);
}
CodePudding user response:
I'm not sure if this might be the issue, but I'm thinking maybe it has something to do with te useEffect dependency array, since you have no dependency array, it's making the api call on every render, which in some cases could cause more render because you are changing the state. Try setting the useEffect like this
function App() {
const [props, setProps] = useState({});
useEffect(() => {
axios
.get(`http://localhost:9000/sessions/list`)
.then((row) => setProps(row.data));
}, []);
return (
<div>
<TestCard
name={props.name}
description={props.description}
preview_image={props.preview_image}
/>
</div>
);
}
CodePudding user response:
First, you need to add a dependency to useEffect, especially when making an API call. Without it, it will make the API call every time the component re-renders and that is an endless cycle.
useEffect(() => {
axios
.get(`http://localhost:9000/sessions/list`)
.then((row)=>setProps(row.data))
},[])
The issue with your code is that you are passing in three properties to TestCard but expecting one. Here is the working version:
function TestCard({name, description, preview_image}) {
return (
<Card sx={{ maxWidth: 345 }}>
<CardActionArea>
<CardMedia
component="img"
height="300"
image={preview_image}
alt={name} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{description}
</Typography>
<Typography variant="body2" color="text.secondary">
{description}
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
}
export default TestCard