'withRouter' is not exported from 'react-router-dom' - reactjs

Failed to compile. Attempted import error: 'withRouter' is not exported from 'react-router-dom'.
My code like, also I have installed react-router-dom an react-route and I have respin the app 10 time now
import React from 'react';
import {withRouter} from 'react-router-dom';
import './menu-item.scss';
const MenuItem = ({ title, imageUrl, size, history }) => (
<div className={`${size} menu-item`}>
<div
className='background-image'
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className='content'>
<h1 className='title'>{title.toUpperCase()}</h1>
<span className='subtitle'>SHOP NOW</span>
</div>
</div>
);
export default withRouter(MenuItem);

If you accidentally installed react-router-dom v6 then the withRouter HOC no longer exists. Either revert back to v5 (run npm install -s react-router-dom#5), or roll your own custom withRouter HOC to inject the props you need or convert the components to function components and use the React hooks.
Create custom withRouter Higher Order Component
From the FAQ: What happened to withRouter I need it
import {
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
Convert to function component
There is now also no longer a history object to use, it was replaced by a navigate function accessed via the useNavigate hook. It's not clear where history was being used previously, but if you need to imperatively navigate the following is how you access the navigation. If staying with v6 then the following is how to access the navigate function.
import React from 'react';
import { useNavigate } from 'react-router-dom';
import './menu-item.scss';
const MenuItem = ({ title, imageUrl, size }) => {
const navigate = useNavigate();
// navigate("/targetPath")
return (
<div className={`${size} menu-item`}>
<div
className='background-image'
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className='content'>
<h1 className='title'>{title.toUpperCase()}</h1>
<span className='subtitle'>SHOP NOW</span>
</div>
</div>
)
};
export default MenuItem;

You can use useLocation hook and destructure 'pathname' property from it to make the navigated link in the onClick() function dynamic.
Here's a sample of the code that worked for me:
import React from "react";
import { useLocation, useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, linkUrl, match }) => {
let navigate = useNavigate();
// destructured "pathname" property from useLocation()
let { pathname } = useLocation();
// consoloe.log(pathname)
return (
<div className={`${size} menu-item`} onClick={() => navigate(`${pathname}${linkUrl}`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;

thanks to Drew Reese -great shout-, and similar to Switch ( will throw the same error ) here is the downgrade command, just make sure you are in the right directory
npm install react-router-dom#5.0.0

try this it worked for me
import React from "react";
import { useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, linkUrl, match }) => {
const navigate = useNavigate();
return (
<div className={`${size} menu-item`} onClick={() => navigate(`hats`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
></div>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;

in menu-item.component.jsx you can use the useNavigate just like this one
import React from "react";
import { useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, linkUrl, match }) => {
let navigate = useNavigate();
return (
<div className={`${size} menu-item`} onClick={() => navigate(`${linkUrl}`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
></div>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;
Also, in App.js you should import Routes and Route from react-router-dom and make your code like this:
import React from "react";
import { Routes, Route } from "react-router-dom";
import "./App.css";
import HomePage from "./pages/homepage/homepage.component";
const HatsPage = () => (
<div>
<h1>Hats page</h1>
</div>
);
function App() {
return (
<div>
<Routes>
<Route exact path="/" element={<HomePage />} />
<Route path="/hats" element={<HatsPage />} />
</Routes>
</div>
);
}
export default App;
As for me, this works.

Related

How to pass data from component to another component in react hooks with onClick

On click on the blogItem, how can I pass data from blogItem.js component to blogDetails.js component ? However the blogItem component is imported in Home.js component. May I know where do I add the click action ? Could someone please share an example ?
CodeSandboX link
https://codesandbox.io/s/gallant-water-5bmueq?file=/src/blogItem.js:0-1876
// App.js
import { BrowserRouter, Route, Routes, Switch } from "react-router-dom";
import Home from "./src/Home";
import BlogItem from "./src/blogItem";
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/blogItem" element={<BlogItem />}></Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
//Home.js
import "./styles.css";
import React, { useState, useEffect, useCallback } from "react";
import BlogItem from "./blogItem";
const Home = (props) => {
const [blogItem, setBlogItem] = useState(props);
useEffect(() => {
setBlogItem(props);
}, [props]);
return (
<div id="App">
<BlogItem />
</div>
);
};
export default Home;
// BlogItem.js
import "./styles.css";
import React, { useState, useEffect, useCallback } from "react";
const blogData = [
{
id: 1,
date: "25 Jan 2023",
photo: "https://picsum.photos/80",
heading: "Cypress setup blog",
blogDetails:
"Best heading added here. The most relevant data added here. Greatest of all time. Wont be a good idea play here always."
},
{
id: 2,
date: "22 Jan 2022",
photo: "https://picsum.photos/80",
heading: "React state details",
blogDetails:
"Best heading added here. The most relevant data added here. Greatest of all time. Wont be a good idea play here always."
}
];
const BlogItem = ({ id, date, photo, heading, blogDetails }) => {
const [searchResults, setSearchResults] = useState(blogData);
const [state, setState] = useState({ id, date, photo, heading, blogDetails });
const Columns = () => (
<div className="blogItems">
<div className="row">
<div className="blogArea">
{searchResults.map(({ id, date, photo, heading, blogDetails }) => (
<a key={id}>
<div className="blogImageSection">
<img alt="id" src={photo} />
<div key={id} className="dataArea">
<span className="dataDate">{date}</span>
<span className="tags">cypress</span>
<h3>{heading}</h3>
<p>
Best heading added here. The most relevant data added here.
Greatest of all time. Wont be a good idea play here always.
</p>
<a href="_blank" className="readmoreLink">
Read more →
</a>
</div>
</div>
</a>
))}
</div>
</div>
</div>
);
return <Columns {...state} />;
};
export default BlogItem;
// BlogDetails.js
import React from "react";
const BlogDetails = () => {
return (
<div id="App">
<div className="blogDetailsSection">
<div className="row">
<div className="individual-blogs">
<h2>ddd</h2>
<p>Blog details</p>
<pre>
<code>const data = []; data.push("soccer");</code>
</pre>
</div>
</div>
</div>
</div>
);
};
export default BlogDetails;
First of all make the browserRouter in the index.js file and remove it from the app.js file and create a Route for the BlogDetails component :
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/blogItem" element={<BlogItem />}></Route>
<Route path="/blogDetails" element={<BlogDetails />}></Route>
</Routes>
</BrowserRouter>
Then you have to install 'react-router-dom' package.
npm i react-router-dom
In BlogItem.js file import useNavigate from it :
import { useNavigate } from "react-router-dom";
const navigate = useNavigate(); // from inside the function component
Now you add onClick to the element that you want to click on it to be redirect to /blogDetails for example here :
<div className="blogImageSection"
onClick={() =>
navigate('blogDetails', { state: {id, date, photo, heading, blogDetails } }) // this is how to pass data with useNavigate
}> ... </div>
Finally in BlogDetails.js file :
import { useLocation } from "react-router-dom";
const location = useLocation(); // from inside the function component
And you can access the passed data like this :
const myRecievedData = location.state

Getting Invalid Hook Error in React App after trying to wrap app in provider

I am building a mock e-commerce store using react and after laying the groundwork for the website, I installed the package react-use-cart (https://www.npmjs.com/package/react-use-cart) to handle the items being added to the cart and to be used in a checkout page. I wrapped my app in the Cart Provider that was given by the react-use-cart package and set up the cart functions on my product pages but now my app does not load anything on startup and gives me an invalid hook call error. I have tried wrapping the app in the index.js file with the provider as well and that gives the same error.
import React, { useState } from "react";
import './css/App.css';
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
import NavBar from "./components/NavBar"
import ProductsScreen from "./screens/ProductsScreen"
import ProductDetailScreen from "./screens/ProductDetailScreen"
import HomeScreen from "./screens/HomeScreen"
import LoginScreen from "./screens/LoginScreen"
import RegisterScreen from "./screens/RegisterScreen";
import CartScreen from "./screens/CartScreen"
import { CartProvider } from "react-use-cart";
const App = () => {
return (
<>
<BrowserRouter>
<CartProvider>
<NavBar />
<Routes>
<Route path='/' element={<HomeScreen/>}/>
<Route path='/products' element={<ProductsScreen/>}/>
<Route path='/product/:id' element={<ProductDetailScreen/>}/>
<Route path='/login' element={<LoginScreen/>}/>
<Route path='/register' element={<RegisterScreen/>}/>
<Route path='/cart' element={<CartScreen/>}/>
</Routes>
</CartProvider>
</BrowserRouter>
</>
)
}
export default App;
import { useState, useEffect }from 'react'
import { Link, useParams } from 'react-router-dom'
import axios from 'axios'
import "../css/ProductDetailScreen.css"
import { useCart } from "react-use-cart";
// import Slideshow from '../components/SlideShow'
const { addItem, updateItemQuantity } = useCart();
const ProductDetailScreen = ( {match} ) => {
const [product, setProduct] = useState({})
const { id } = useParams()
useEffect(() => {
const getProduct = async () => {
const { data } = await axios.get(`/api/products/${id}`)
setProduct(data)
}
getProduct()
}, [])
return (
<>
<Link to ='/products'>Go Back</Link>
<div className="wrapper">
<div className="detail-grid">
<div className='imgContainer'>
<img className='cover_img1' src={product.cover_img} alt='Videogame Cover Art'/>
<div className='carousel'>
{product.images?.map((image, index) => (
<img key={index} src={image} alt="Videogame Gameplay"></img>
))}
</div>
{/*Replace carousel div with actual image slideshow*/}
</div>
<div>
<div className='textContainer'>
<h1 className='title1'>{product.title}</h1>
<h3 className='descriptionHeader'>Description:</h3>
<p className='description1'>{product.description}</p>
<h3 className='developer1'>Developer: {product.developer}</h3>
<h3 className='publisher1'>Publisher: {product.publisher}</h3>
<h3 className='releaseDate1'>Release Date: {product.releaseDate}</h3>
<h3 className='genre1'>Genre: {product.genre}</h3>
</div>
<div className='checkOutContainer'>
<h3 className='price1'>Price: ${product.price}</h3>
<button onClick={() => updateItemQuantity(product.id, product.quantity - 1)}> - </button>
<span>{product.quantity}</span>
<button onClick={() => updateItemQuantity(product.id, product.quantity + 1)}> + </button>
<button onClick={() => addItem(product)} className='addCart' type='button'>Add to Cart</button>
</div>
</div>
</div>
</div>
</>
)
}
export default ProductDetailScreen

How do I use the Use Navigate from React Router on a button that links to different pages?

I have a button that represents shop now that upon click it redirects you on different pages and the card elements have been mapped on external data.
I want this button to navigate to different pages kindly help.
const data =[
{
id:"Extensions",
Title:"Electrical Collections",
img:"/Assets/Electricals/Extlogo.png",
},
{
id:"Phone Accesorries",
Title:"Phone Accessories",
img:"/Assets/Phone/phoneacc.png",
},
{
id:"Homeware",
Title:"Homeware Collections",
img:"/Assets/Home/home.png",
},
]
function Home() {
let Navigate =useNavigate();
const handleElectricalPage = () =>{
Navigate("/extensionproduct")
}
<div className='cardContainer'>
{data.map((item )=>(
<card>
<div className='imageContainer'>
<img src={item.img} alt='Extension logo'/>
</div>
<div className='contentsContainer'>
<h2>{item.Title}</h2>
<div className='iconButtonContainer'>
<button onClick={handleElectricalPage}>Shop Now</button>
<ArrowForwardIcon className='arrowIcon'/>
</div>
</div>
Example from the react router https://reactrouter.com/docs/en/v6/api#usenavigate
navigate("../success", { replace: true });
You need to make an onClick handler (handleElectricalPage) dynamically, consider something like this.
function Home() {
let navigate =useNavigate();
return (
<div className='cardContainer'>
{data.map((item) => (
<card>
<button
onClick={() => navigate(`/externalProduct/${item.id}`)}
>
Shop Now
</button>
</card>
)}
</div>
}
You can also use Link which handles everything by itself
<Link to={`/externalProduct/${item.id}`}>
<button>Shop now</button>
</Link>
App.jsx
import { Routes, Route, Navigate } from "react-router-dom";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />}>
<Route path="post/:id" element={<Detail />} />
</Route>
</Routes>
</div>
);
}
export default App;
Post.jsx
import React, { useState } from "react";
import {useNavigate} from 'react-router-dom'
export default function Post(props) {
const navigate = useNavigate()
{props.posts.map((post) => {
return (
<div className="post__container" key={post.id}>
<h4>
{post.id} {post.title}
</h4>
<p>{post.body}</p>
<button onClick={() => {return navigate(`${post.id}`)}}>Detail</button>
</div>
);
})}
}
Detail.jsx
import axios from 'axios'
import React, {useEffect, useState } from 'react'
import {useParams} from 'react-router'
export default function Detail (props) {
const params = useParams()
const [posts, setPosts] = useState({})
async function getById(id) {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts/" + id)
setPosts(response.data)
}
useEffect(() => {
getById(params.id)
}, [params.id])
return (
<div>
<h2>Detail page: {params.id}</h2>
<h4>{posts.title}</h4>
<h5>{posts.body}</h5>
</div>
)
}

How to pass values in the <Link to = {}> and get them from another component using [react / typescript]

I would like to see how I can pass the id inside the <Link to = {}> using typescript. Then in the SeriesSection component get the id of the link.
SerieComponent.tsx
import React from 'react';
import { Link } from "react-router-dom";
import Serie from '../../interfaces/Serie/Serie';
type T = {
serie: Serie
};
const SerieComponent: React.FC<T> = ({ serie: { id, title, sinopsis, poster, rating, year, extra } }) => {
let channel = extra.map(x => { return x.channel });
return (
<Link to={}/>
<div className="post-2930 movie type-movie status-publish has-post-thumbnail hentry movie_genre-action">
<div className="movie__poster">
<br />
<a className="masvideos-LoopMovie-link masvideos-loop-movie__link movie__link">
<img width="300" height="450" src={poster} className="movie__poster--image" alt={title} />
<img width="300" height="450" src={poster} className="movie__poster--image" alt={title} sizes="(max-width: 300px) 100vw, 300px" />
</a>
</div>
<div className="movie__body">
<div className="movie__info">
<div className="movie__info--head">
<div className="movie__meta"><span className="movie__meta--release-year">{year}</span><span className="movie__meta--genre">{channel}</span></div>
<a className="masvideos-LoopMovie-link masvideos-loop-movie__link movie__link">
<h3 className="masvideos-loop-movie__title movie__title">{title}</h3>
</a>
</div>
<div className="movie__short-description">
<div>
<p>{sinopsis}</p>
</div>
</div>
</div>
</div>
</div>
</Link>
)
};
export default SerieComponent;
This component is where I want to get the id of the link.
import React from 'react';
const SerieSection: React.FC = () => {
return(
<div>
</div>
)
};
export default SerieSection;
If you notice I already referred to the route
<Route exact path="/serie-section/:id" component={SerieSection}></Route>
import React from 'react';
import { Switch, Route, Redirect, Link } from 'react-router-dom';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import Home from '../Home/index';
import About from '../About/index';
import Footer from '../Footer/index';
import SerieSection from '../SerieSection/index';
import useStyles from './styles';
require('../../db/index.ts');
const App: React.FC = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<Button component={Link} to="/" color="inherit">Home</Button>
<Button component={Link} to="/about" color="inherit">About</Button>
</Toolbar>
</AppBar>
<div className="App">
<Switch>
<Route exact path="/" component={Home}></Route>
<Route exact path="/about" component={About}></Route>
<Route exact path="/serie-section/:id" component={SerieSection}></Route>
<Redirect to="/" />
</Switch>
<Footer/>
</div>
</div>
)
}
export default App;
<Link to={{
pathName: "/yourpathname",
someProp:{foo:"bar"}
}}>Your Path</Link>
and than in you component that this Link leads to
console.log("test: ", props.location.someProp)
If the second component is class dont forget this keyword
I had to refer to RouteComponentProps
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
interface State {
id: string;
}
interface Props extends RouteComponentProps<State>{
}
const SerieSection: React.FC<Props> = (props) => {
let id = props.match.params.id;
return(
<div>
<h1>{id}</h1>
</div>
)
};
export default SerieSection;

Clickable routing without link tag in react js

I want to navigate to another page when that component is clicked so i used to do that easily with Link tag but i want to navigate without link tag . is there any routing concepts rather that this Link tag . can someone clarify me pls .Here i attached my code ,
// Libraries
import React, { Component, Button, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router-dom'
import {Row} from './dataTables/Row';
class Customers extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.customersActions.fetchCustomers();
}
render() {
return (
<div className="customer-container">
<div className="body-container">
<div className="row-scroll">
{this.props.customersData.customers.filter(function(customer, index) {
if(index != 0) return true;
else return false;
}).map(customer =>
<Link to={'/customer/'+ customer.customer_id} key={customer.customer_id} className="line-removal">
<Row customer={customer} />
</Link> // what are all the other options instead of Link ???
)
}
</div>
</div>
</div>
);
}
}
function mapStateToProps(state, ownProps) {
return { customersData: state.customers };
}
export default connect(
})
)(Customers);
above is my code , can someone pls help me out from this.
You can use history.push() and standard react onClick to build the same behaviour like <Link /> provides.
Working demo (click on "Go to About" button): https://codesandbox.io/s/ER23MMvL0
Home.js
import React from 'react';
export default ({ history }) => {
const handleClick = () => {
history.push('/about');
};
return (
<div>
<h1>Home</h1>
<button onClick={handleClick}>Go to About</button>
</div>
);
};
index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';
const styles = {
fontFamily: 'sans-serif',
textAlign: 'center',
};
const App = () => (
<Router>
<div style={styles}>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</div>
</Router>
);
render(<App />, document.getElementById('root'));
You can use useNavigate() in Router v6.
import { useNavigate } from "react-router-dom";
const Home = () => {
const navigate = useNavigate();
<button onCLick={() => navigate("/about")}>Click me!</button>;
};

Resources