in react I want to run an application-related react-router; that is fine; the problem is that specific code, such as "react-router-dom": "6.8.1," does not run in the latest react version and throws an error.
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports."
But if you change the version, it's working fine, like in "react-router-dom": "5.2.1", This code is working fine, ,so my question is in "react-router-dom": :6.8.1 How to successfully run that code?in my App.js in code structure which thing should I have to change that code will run perfectly in 6.8.1 too?
import { useState } from "react";
import {
BrowserRouter as Router,
generatePath,
Switch,
Route,
useHistory,
useParams
} from "react-router-dom";
const products = [
{
id: "1",
name: "Product 1"
},
{
id: "2",
name: "Product 2"
},
{
id: "3",
name: "Product 3"
}
];
const Products = () => {
const { id } = useParams();
console.log(id);
return (
<div>
<p>Lorem Ipsum</p>
<p>Id: {id}</p>
</div>
);
};
const Home = () => {
const [id, setId] = useState();
const history = useHistory();
console.log(history)
const handleProceed = (e) => {
id && history.push(generatePath("/products/:id", { id }));
};
return (
<div
style={{ display: "flex", flexDirection: "column", alignItems: "center" }}
>
<div>
{products.map((product, i) => (
<button
key={i}
onClick={(e) => {
setId(product.id);
}}
>
{product.name}
</button>
))}
</div>
<button onClick={handleProceed} style={{ width: "250px" }}>
Click
</button>
</div>
);
};
export default function App() {
return (
<div className="App">
<header>Heading</header>
<Router>
<Switch>
<Route path="/products/:id">
<Products />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
</div>
);
}
react-router@6
brought with it a ton of breaking changes. You should review the Upgrading from v5 migration guide for the full details.
The Switch
component was replaced by the Routes
component which is required to directly wrap Route
s you are rendering, and the useHistory
hook was replaced by the useNavigate
hook.
import { useState } from "react";
import {
BrowserRouter as Router,
generatePath,
Routes,
Route,
useNavigate,
useParams
} from "react-router-dom";
useNavigate
returns a navigate
function instead of a "history" object. Call navigate
to issue imperative navigation actions.
const Home = () => {
const [id, setId] = useState();
const navigate = useNavigate();
const handleProceed = () => {
navigate(generatePath("/products/:id", { id }));
};
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center"
}}
>
<div>
{products.map((product) => (
<button
key={product.id}
type="button"
onClick={() => {
setId(product.id);
}}
>
{product.name}
</button>
))}
</div>
<button
type="button"
disabled={!id}
onClick={handleProceed}
style={{ width: "250px" }}
>
Click
</button>
</div>
);
};
The Route
component API/props changed, all the routed content is rendered on the Route
component's element
prop.
export default function App() {
return (
<div className="App">
<header>Heading</header>
<Router>
<Routes>
<Route path="/products/:id" element={<Products />} />
<Route path="/" element={<Home />} />
</Routes>
</Router>
</div>
);
}