Reputation: 159
I'm creating a React web-app for displaying Covid data from an API. I'm having problems with React routing.
Here you can see the files with changes for version 5.3.0 of react-router-dom and for version 6.0.0. The version commented with the version 5.3.0 is actually working, in the home component I get the list of nations and a button that links to deatils page with the details for the selected nation. With the version 6.0.0 in the ViewDetails page the state is always null and I'm not seeing the details for the selected country and I'm not understanding how to solve this.
App.js
import React from "react";
import './App.css';
import Home from "./Home";
import ViewDetails from "./ViewDetails";
/*v6.0.0*/
import { BrowserRouter, Routes, Route, Link} from "react-router-dom";
/*5.3.0
import { BrowserRouter, Route, Switch } from "react-router-dom";
*/
function App() {
return (
/* VERSION 5.3.0
<BrowserRouter>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route
exact
path="/view-details/:id"
component={ViewDetails}
/>
</Switch>
</div>
</BrowserRouter>
*/
/* VERSION v6.0.0*/
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/view-details/:id" element={<ViewDetails />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Home.js
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom"
import Axios from "axios";
import { v4 as uuidv4 } from "uuid";
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import Button from '@mui/material/Button';
import './styles/home.css'
import Box from '@mui/material/Box';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import Divider from '@mui/material/Divider';
import { styled } from '@mui/material/styles';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
const Home = props => {
const [covidsData, setCovidData] = useState([]);
const fetchCovidData = async () => {
const { data } = await Axios.get(
"https://corona.lmao.ninja/v2/countries?yesterday=&sort="
);
const covidData = data;
for(let i=0; i < covidData.length; i++)
{
covidData[i]["id"] = uuidv4()
}
setCovidData(covidData);
console.log(covidData);
};
useEffect(() => {
fetchCovidData();
}, []);
/* SAME CODE FOR v5.3.0 AND v6.0.0 */
return (
<Grid container
spacing={0}
direction="column"
alignItems="center"
justifyContent="center"
style={{ minHeight: '100vh' }}>
<Typography variant="h1" component="h1">
Covid data
</Typography>
<List>
{covidsData.map(covidData => {
return (
<div key={covidData.id}>
<ListItem >
<ListItemText primary={covidData.country} />
<Link className="link-details"
to={{
pathname: `/view-details/${covidData.id}`,
state: { covidsData: covidData }
}}
>
<Button style={{marginLeft: '0.5em', height:'1.8em'}} variant="contained">View</Button>
</Link>
</ListItem>
<Divider />
</div>
);
})}
</List>
</Grid>
);
};
export default Home;
ViewDetails.js
import React from "react";
import { useLocation, Link } from "react-router-dom";
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import './styles/viewdetails.css'
const ViewDetails = () => {
/*SAME CODE FOR v5.3.0 AND v6.0.0 */
const { state } = useLocation();
console.log(state);
return (
<div>
<Typography variant="h1" component="h1">
Country: {state.covidsData.country}{" "}
</Typography>
<img
src={state.covidsData.countryInfo.flag}
alt="new"
/>
<Typography variant="h2" component="h2">
Today cases
</Typography>
<Typography variant="p" component="p">
{state.covidsData.todayCases}
</Typography>
<Link to="/" className="back-to-list">
<Button variant="contained">Back</Button>
</Link>
</div>
);
};
export default ViewDetails;
When I use the version 5.3.0 everything is working good and I can see the data both in the Home and in the ViewDetails component. If I install the version 6.0.0 I'm getting this error in the ViewDetails page:
TypeError: Cannot read properties of null (reading 'covidsData')
ViewDetails
F:/React/Cvid/cvid/src/ViewDetails.js:13
10 |
11 | return (
12 | <div>
> 13 | <Typography variant="h1" component="h1">
| ^ 14 | Country: {state.covidsData.country}{" "}
15 | </Typography>
16 | <img
How can I switch to version 6.0.0 of react-router-dom and make the ViewDetails page work again?
Thank you all.
Upvotes: 1
Views: 540
Reputation: 202836
The react-router-dom
Link
component API changed a bit from v5 to v6.
state
is now a "top-level" prop.
interface LinkProps extends Omit< React.AnchorHTMLAttributes<HTMLAnchorElement>, "href" > { replace?: boolean; state?: State; to: To; }
In the Home
component you can just move the state
from the to
object up to be a prop on the Link
.
<List>
{covidsData.map((covidData) => {
return (
<div key={covidData.id}>
<ListItem>
<ListItemText primary={covidData.country} />
<Link
className="link-details"
to={`/view-details/${covidData.id}`}
state={{ covidsData: covidData }} // <-- state is a prop
>
<Button
style={{ marginLeft: "0.5em", height: "1.8em" }}
variant="contained"
>
View
</Button>
</Link>
</ListItem>
<Divider />
</div>
);
})}
</List>
Upvotes: 1