Converting stateless React component having arguments to stateful - javascript

Inside my React JS project, I am working on the PrivateRoutes.
I have gone through this example of private routing and authenticating using react-router-dom.
https://reacttraining.com/react-router/web/example/auth-workflow
According to this documentation, they have created a PrivateRoute as a stateless component.
But my requirement is to convert it to stateful React component as I want to connect my PrivateRoute component to redux store.
Here is my code.
stateless component
import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {auth} from './Authentication';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
auth.isAuthenticated ? (
<Component {...props} />
) : (
<Component {...props} action="login"/>
)
}
/>
);
export default PrivateRoute;
I converted this component to stateful React component like this.
stateful React component
import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {auth} from './Authentication';
import {connect} from 'react-redux';
class PrivateRoute extends React.Component {
render({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
this.props.customer.isAuthenticated ? (
<Component {...props} />
) : (
<Component {...props} action="login"/>
)
}
/>
);
}
}
export default connect(state => state)(PrivateRoute);
Here, I am reading the data from redux store to check whether the user is authenticated or not.
But the way I am converting the stateless component to stateful isn't correct.
Am I passing the arguments render({ component: Component, ...rest }) correctly?
Will connecting the PrivateRoute with redux store create any problem with props as state=>state will map state to props as well as ...rest will have props object?
Not sure what is happening inside the code.
Update
AppRouter.js
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import {TransitionGroup, CSSTransition} from 'react-transition-group';
import PrivateRoute from './PrivateRoute';
import HomePage from './../components/HomePage';
import AboutUs from './../components/AboutUs';
import ContactUs from './../components/ContactUs';
import PageNotFound from './../components/PageNotFound';
import RestaurantList from '../components/RestaurantList';
import RestaurantMenu from '../components/RestaurantMenu';
import UserDetails from '../components/UserDetails';
import OrderConfirmation from '../components/OrderConfirmation';
import CustomerAccount from '../components/CustomerAccount';
import Logout from '../components/sections/Logout';
export default () => {
return (
<BrowserRouter>
<Route render={({location}) => (
<TransitionGroup>
<CSSTransition key={location.key} timeout={300} classNames="fade">
<Switch location={location}>
<Route path="/" component={HomePage} exact={true}/>
<Route path="/about" component={AboutUs} />
<Route path="/contact" component={ContactUs} />
<Route path="/restaurants" component={RestaurantList} />
<Route path="/select-menu" component={RestaurantMenu} />
<PrivateRoute path="/user-details" component={UserDetails} />
<PrivateRoute path="/order-confirmation" component={OrderConfirmation} />
<PrivateRoute path="/my-account" component={CustomerAccount} />
<PrivateRoute path="/logout" component={Logout} />
<Route component={PageNotFound} />
</Switch>
</CSSTransition>
</TransitionGroup>
)} />
</BrowserRouter>
);
}

In general, converting a stateless functional component (SFC) to a Component is done like this:
Create the class shell for it.
Copy the SFC's body to the render method. If the SFC was an arrow function, add a return as necessary to render.
Change any references to props in the render method to this.props (or just add const { props } = this; at the top). SFCs receive their props in their arguments, but a component receives them as arguments to its constructor; the default constructor will save them as this.props.
In your case, it's using destructuring on its arguments, so you could do the same with this.props on the right-hand side of the destructuring:
const { component: Component, ...rest } = this.props;
That's it. In your code, you've added parameters to the render function, but it doesn't get called with any arguments, and you've only changed props to this.props a bit haphazardly (including changing auth.isAuthenticated to this.props.customer.isAuthenticated for some reason).
So applying 1-3 above:
// #1 - the shell
class PrivateRoute extends React.Component {
// #2 - `render`, with the body of the SFC inside
render() {
// #3 - destructure `this.props`
const { component: Component, ...rest } = this.props;
// #2 (part 2) - add `return`
return <Route
{...rest}
render={props =>
auth.isAuthenticated ? (
<Component {...props} />
) : (
<Component {...props} action="login"/>
)
}
/>;
}
}

Your stateful component should be:
class PrivateRoute extends React.Component {
render() {
const { component: Component, ...rest } = this.props;
return (
<Route
{...rest}
render={props =>
this.props.customer.isAuthenticated ? (
<Component {...props} />
) : (
<Component {...props} action="login"/>
)
}
/>
);
}
}
Please see that there is some issue in render parameter of Route. Here you have props as function param but still using this.props.customer, don't know the use case hence please fix it as per your application.
Apart from it Component and all the other data is already there in props of the component. It won't be available in parameter of render method in component. Same destructuring as available in stateless component can be written in render method as shown in code above.
Will connecting the PrivateRoute with redux store create any problem with props?
Yes, it would. The way you have connected to the store will make store data available in props of component but external props passed to component will not be available.
For that you have to handle it in mapStateToProps function:
const mapStateToProps = (state, ownProps) => ({
...state,
...ownProps
});
Here mapStateToProps has second parameter which has the external own props passed to component. So you have to return it as well to make it available in component props.
Now connect would be like:
export default connect(mapStateToProps)(PrivateRoute);

I was having two queries.
1) How to convert to Stateful Functional Component?
2) After connecting to the redux store will the props create a problem?
My first query was solved by the answer provided by T.J.Crowder.
For a second query, I tried connecting the redux store to the PrivateRoute and I did get the data I was looking for.
Here is the code which worked for me.
import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {connect} from 'react-redux';
class PrivateRoute extends React.Component {
render() {
const { component: Component, ...rest } = this.props;
const {customer} = this.props;
return <Route
{...rest}
render={props =>
customer.isAuthenticated ? (
<Component {...props} />
) : (
<Component {...props} action="login"/>
)
}
/>;
}
}
export default connect(state => state)(PrivateRoute);
Using this code I got the data that is coming from the routes, as well as the redux state inside the props.
This is getting data coming from the routes
const { component: Component, ...rest } = this.props;
This is the data coming from the redux store.
const {customer} = this.props;

#T.J.Crowder has already written how to convert stateless component to stateful component in those 3 steps. so i will just write about connecting component to redux store like you did.
I think connected components should always define mapStateToProps and explicitly declare which data they depend on from the state.
because the connected component rerenders if the connected property changes. so it would be a bad idea to connect the whole application state to a component. as it would mean that wheneever anything changes in application state rerender all connected components.
better we define explicitly like the following that we depend on a property called data (or anything you have) from the state. so in this case this component will only rerender if state.data changes it wont rerender if state.xyz changes.
and this way you can take state.data and name it as you wish so it would not conflict with any existing props of the component.
const mapStateToProps = (state, ownProps) => ({
data: state.data
});
export default connect(mapStateToProps)(PrivateRoute);

Related

How do I pass props from from redux store

I have a simple app that's using redux and react-router. I wrapped my app component in a provider tag so that it has access to the store. I connected (in App.js) the mapStateToProps and mapStateToDispatch in the App.js. I'm not sure how to pass the function I defined in App.js to a child component since I'm using route. I tried doing the render trick but it didn't work. If I can pass it to that CelebrityPage component, how would I receive it in the file? Any help would be appreciated.
This is my App.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
import './App.css';
import Clarifai from 'clarifai'
// import Particles from 'react-particles-js';
// import particlesOptions from './particleOptions'
import { Signin } from './components/signin/Signin';
import Register from './components/register/Register';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import { setSearchField } from './context/Actions'
import FacePage from './Containers/FacePage';
import CelebrityPage from './Containers/CelebrityPage';
import ControllerPage from './Containers/ControllerPage';
const mapStateToProps = state => {
return {
input: state.input
}
}
const mapDispatchToProps = (dispatch) => {
return {
handleSearchChange: (event) => dispatch(setSearchField(event.target.value))
}
}
...
render() {
return (<Router>
<Switch >
<Route path='/celebrity' exact render={props => <CelebrityPage{...props} handleSearchChange={this.handleSearchChange} />} />
<Route path='/' exact component={Register} />
<Route path='/signin' exact component={Signin} />
<Route path='/contoller' exact component={ControllerPage} />
<Route path='/face-detection' exact component={FacePage} />
</Switch>
</Router>)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
If you are going to pass store actions and states into the child components, it means you are refusing to use the advantages of redux. The best approach should be connect any of your component that needs to access to the actions or state to the store. Doing connection at the root component level and passing the props to the child components is not a good solution.
I think what robert is saying is what you'd probably want to do. Don't try to pass your props inside of your <Route>. Instead do your connect mapDispatchToProps and your mapStateToProps inside your CelebrityPage Component.
Once you do the wrapping inside of the Celebrity Page component you should have access to the props and functions that you have defined.
...
// keep all the previous imports from your App.Js
render() {
// have your router like this
return (<Router>
<Switch >
<Route path='/celebrity' exact component ={CelebrityPage} />
<Route path='/' exact component={Register} />
<Route path='/signin' exact component={Signin} />
<Route path='/contoller' exact component={ControllerPage} />
<Route path='/face-detection' exact component={FacePage} />
</Switch>
</Router>)
}
}
export default App
Example Celebrity page
import React from 'react'
import { connect } from 'react-redux'
class CelebrityPage extends React.Component {
// put your mapStateToProps and mapDispatch function heres instead of app.js
mapStateToProps() {
}
mapDispatchToProps {
// bind your handlesearch function to props here
}
render() {
return (
<div>
<input />
<button onClick={this.props.handleSearchChange}/>
</div>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CelebrityPage)

Pascal case error for dynamically adding component name to Reactjs Route's render method

I am trying to get a component to render dynamically. The name for the component is getting pulled from the state. The name is in pascal case but still it throws a pascal case error. For instance, the value that I am trying on is "HeroBanner". If I put this directly, it works fine. If get this dynamically via state and then assigning it to a variable, it backfires with pascal case error.
Here's my code
import '#babel/polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Redirect, withRouter} from 'react-router-dom'
import { createBrowserHistory } from 'history';
import HeroBanner from './IssueList.jsx';
import IssueTable from './IssueTable.jsx';
import {PropTypes} from 'prop-types';
import {Header} from './Header.jsx';
import Demo from './Cropcrop.jsx';
import {Receiver} from 'react-file-uploader';
const contentNode = document.querySelector("#contents");
const NoMatch = () => <p>404 no result</p>
class App extends React.Component{
constructor(){
super();
this.state = {
currentLocation: ""
}
this.changeLocation = this.changeLocation.bind(this)
}
changeLocation(e){
this.setState({
currentLocation: e
})
}
render(){
const Component= this.state.currentLocation === ''? "HeroBanner" : this.state.currentLocation
return(
<div>
<BrowserRouter>
<Header/>
<Redirect from="/" to="/selection"></Redirect>
<Switch>
<Route exact path={"/"+ Component} render={(props) => <Component />} />
<Route exact path="/selection" render={(props) => <IssueTable {...props} onChange={this.changeLocation} />} />
<Route path="/*" component={NoMatch}/>
</Switch>
</BrowserRouter>
<Component/>
</div>
)
}
}
const RoutedApp = () => (
<App/>
);
ReactDOM.render(<RoutedApp />, contentNode);
if(module.hot){
module.hot.accept();
}
You're not allowed to specify component dynamically like this in React (specifying a string instead of a type):
render={(props) => <Component />}
It should be something like:
const Component = this.state.currentLocation === '' ? HeroBanner : SomeOtherComponent;
I had a similar situation in the project I'm working on and ended up with creating a map between a certain string value (in my case it was the name of a tab, coming from the URL) and component's type:
const componentsMap = {
home: HomeComponent,
about: AboutComponent,
...
}
const Component = componentsMap[myStringValue];
That last piece of code is allowed as you're refering to the component's type, not to some ordinary string which can't be used as valid JSX.
As for routing, I noticed you just set some string value in the state and expect routing to happen. This is not the case as react-router-dom listens for changes in the browser's url/path and you should probably perform manual routing in your case to move to another <Route> view. In the example below I perform navigation in the onDropdownChange handler upon dropdown change.
The way I like to minimize repetition of strings representing route names and component names is to have the dynamic value as param in the URL. Then a <Subroute> component handles all the mapping for that group of routes (you might not need that additional level of nesting, depends on size of app). In the sandbox I created you can see the map I was talking about in the comments. You select the appropriate component based on the tab param in the URL (which holds the value selected from the dropdown).
Example here
EDIT for a question in the comments (11 Aug 2020):
You can also use a neat trick to customize what gets rendered by a route, like this (without having to use render of Route):
<Route exact path={path}>
<ComponentOne {...someProps} />
<ComponentTwo {...someOtherProps} />
<p>Some html too</p>
</Route>
To use render instead (maybe less readable, I prefer the first option, just pass the necessary JSX, wrapped in Fragment if needed):
<Route
exact
render={routeProps => (
<Fragment>
<ComponentOne {...someProps} />
<ComponentTwo {...someOtherProps} />
<p>Some html too</p>
</Fragment>
)}
/>
While the above answer is absolutely correct. Here's how I followed the above the logic.
import '#babel/polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Redirect, withRouter} from 'react-router-dom'
import { createBrowserHistory } from 'history';
import HeroBanner from './IssueList.jsx';
import IssueTable from './IssueTable.jsx';
import {PropTypes} from 'prop-types';
import {Header} from './Header.jsx';
import Demo from './Cropcrop.jsx';
import {Receiver} from 'react-file-uploader';
const contentNode = document.querySelector("#contents");
const NoMatch = () => <p>404 no result</p>
const componentList={
HeroBanner: HeroBanner
}
class RoutedApp extends React.Component{
constructor(){
super();
this.state = {
currentLocation: ""
}
this.changeLocation = this.changeLocation.bind(this)
}
changeLocation(e){
console.log(e)
this.setState({
currentLocation: e
})
}
render(){
const Component= this.state.currentLocation === '' ? NoMatch : componentList[this.state.currentLocation]
console.log(Component)
return(
<div>
<BrowserRouter>
<Header/>
<Redirect from="/" to="/selection"></Redirect>
<Switch>
<Route exact path={"/"+ this.state.currentLocation} component={Component} />
<Route exact path="/selection" render={(props) => <IssueTable {...props} onChange={this.changeLocation} />} />
<Route path="/*" component={NoMatch}/>
</Switch>
</BrowserRouter>
</div>
)
}
}
ReactDOM.render(<RoutedApp />, contentNode);
if(module.hot){
module.hot.accept();
}

how to access redux store from react component for authentication

I'm maintaining a react redux app and trying to get authentication to one of the routes in the app, namely /dashboard . I want to pass in a boolean state from redux store to a prop named authed but struggling... As currently, I just pass in true value as a fake value.
import React from 'react'
import {
HashRouter,
Route,
Link,
Switch,
Redirect
} from 'react-router-dom'
// components that are main pages
import Home from './containers/Home'
import Login from './containers/Login'
import Signup from './containers/Signup'
import NotFound from './containers/NotFound'
import Dashboard from './containers/Dashboard'
import IntersectionForm from './containers/IntersectionForm'
import IntersectionDetail from './containers/IntersectionDetail'
import { connect } from 'react-redux'
const PrivateRoute = ({component: Component, authed, ...rest}) => {
return (
<Route
{...rest}
render={(props) => authed === true
? <Component {...props} />
: <Redirect to={{pathname: '/', state: {from: props.location}}}/>}
/>
)
}
function mapStateToProps (state) {
return state
}
const PrivateRouteContainer = connect(mapStateToProps)(PrivateRoute)
const Routes = (history) => {
return (
<HashRouter history={history}>
<switch>
<Route exact path="/" component={Login}/>
<Route exact path="/signup" component={Signup}/>
<PrivateRouteContainer authed={true} path='/dashboard' component={Dashboard}/>
</switch>
</HashRouter>
)
}
export default Routes
Make a call to your auth end-point (POST) in auth_actions from your componentDidMount function.
dispatch an action once you get the response within actioncreator.
in authReducer - for example: isAuthenticated:true/false and return the payload.
access that value by making your react component connected and within
mapStatetoprops of the component and you can access this boolean
value - using this.props.authValue.
function mapStateToProps (state) {
return state
}
by doing this your component will receive props with all your states across reducers.
for example, if you have:
import { combineReducers } from 'redux'
import todos from './todos'
import counter from './counter'
export default combineReducers({
todos,
counter
})
Then your PrivateRoute will get todos and counter props.
That's why its better if your mapStateToProps grabs just the prop it needs.
function mapStateToProps (state) {
return {
authed: state.nameOfReducer.isAuthed, // or whetever is the value you need to know if user is authorized
}
}
If you, however, don't combineReducers and you have just one reducer in your app then:
function mapStateToProps (state) {
return {
authed: state.isAuthed,
}
}

React Router: access history in rendered Route component

I know there are quite a few questions on this, but I cannot seem to get it to work: I need to access "history" from the child components that are rendered through the Routes. (It receives props from a redux container).
I need to pass down the history object to the components that are rendered in each Route, so that I can this.props.history.push('/route') in the child components. This application was less dynamic before, so each Route was hardcoded with a component={someComponent}; but I found that in doing the Routes dynamically, you need to use render={() => <someComponent />}.
After changing the Routes from component={} to render={() => ...} I lost history in the child components.
My code is something like:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router, Link, Route, Redirect } from 'react-router-dom';
import { Nav_Item } from '.'
import DynamicTab from '.';
export default class NavBar extends React.Component {
constructor(props) {
super(props);
this.state={}
}
render() {
let tabs = [];
let routes = [];
this.props.tabs.forEach( function(tab, index) {
tabs.push(<Nav_Item key={tab.name} path_name={'/' + tab.name} tab_text={tab.label} />);
routes.push(<Route key={tab.name} path={'/' + tab.name} render={() => <DynamicTab tabName={tab.name} tabSpecs={tab} />} />);
})
return (
<Router>
<div>
<div>
<ol>
{ tabs }
</ol>
</div>
<Redirect to={'/' + this.props.tabs[0].name} />
{ routes }
</div>
</Router>
)
}
}
When you use render you actually get props. In the docs they have an example like this:
<Route {...rest} render={props => (
<FadeIn>
<Component {...props}/>
</FadeIn>
)}/>
So you should be able to access history from those props.
Another solution would be to conditionally render a <Redirect/> component. So maybe you have some internal state that you use like this:
// in your components render function..
if(this.state.shouldRedirect) {
return (<Redirect to={yourURL} />);
}
this.props.router and you have access to whatever you want.
in your case you can just do:
this.props.router.push("/newurl");
There is no need to pass the history as a separate property if this component is rendered by the router.

Programmatically Navigate using react-router

I am developing an application in which I check if the user is not loggedIn. I have to display the login form, else dispatch an action that would change the route and load other component. Here is my code:
render() {
if (isLoggedIn) {
// dispatch an action to change the route
}
// return login component
<Login />
}
How can I achieve this as I cannot change states inside the render function.
Considering you are using react-router v4
Use your component with withRouter and use history.push from props to change the route. You need to make use of withRouter only when your component is not receiving the Router props, this may happen in cases when your component is a nested child of a component rendered by the Router and you haven't passed the Router props to it or when the component is not linked to the Router at all and is rendered as a separate component from the Routes.
import {withRouter} from 'react-router';
class App extends React.Component {
...
componenDidMount() {
// get isLoggedIn from localStorage or API call
if (isLoggedIn) {
// dispatch an action to change the route
this.props.history.push('/home');
}
}
render() {
// return login component
return <Login />
}
}
export default withRouter(App);
Important Note
If you are using withRouter to prevent updates from being blocked by
shouldComponentUpdate, it is important that withRouter wraps the
component that implements shouldComponentUpdate. For example, when
using Redux:
// This gets around shouldComponentUpdate
withRouter(connect(...)(MyComponent))
// This does not
connect(...)(withRouter(MyComponent))
or you could use Redirect
import {withRouter} from 'react-router';
class App extends React.Component {
...
render() {
if(isLoggedIn) {
return <Redirect to="/home"/>
}
// return login component
return <Login />
}
}
With react-router v2 or react-router v3, you can make use of context to dynamically change the route like
class App extends React.Component {
...
render() {
if (isLoggedIn) {
// dispatch an action to change the route
this.context.router.push('/home');
}
// return login component
return <Login />
}
}
App.contextTypes = {
router: React.PropTypes.object.isRequired
}
export default App;
or use
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
In react-router version 4:
import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
const Example = () => (
if (isLoggedIn) {
<OtherComponent />
} else {
<Router>
<Redirect push to="/login" />
<Route path="/login" component={Login}/>
</Router>
}
)
const Login = () => (
<h1>Form Components</h1>
...
)
export default Example;
Another alternative is to handle this using Thunk-style asynchronous actions (which are safe/allowed to have side-effects).
If you use Thunk, you can inject the same history object into both your <Router> component and Thunk actions using thunk.withExtraArgument, like this:
import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
import { createBrowserHistory } from "history"
import { applyMiddleware, createStore } from "redux"
import thunk from "redux-thunk"
const history = createBrowserHistory()
const middlewares = applyMiddleware(thunk.withExtraArgument({history}))
const store = createStore(appReducer, middlewares)
render(
<Provider store={store}
<Router history={history}>
<Route path="*" component={CatchAll} />
</Router
</Provider>,
appDiv)
Then in your action-creators, you will have a history instance that is safe to use with ReactRouter, so you can just trigger a regular Redux event if you're not logged in:
// meanwhile... in action-creators.js
export const notLoggedIn = () => {
return (dispatch, getState, {history}) => {
history.push(`/login`)
}
}
Another advantage of this is that the url is easier to handle, now, so we can put redirect info on the query string, etc.
You can try still doing this check in your Render methods, but if it causes problems, you might consider doing it in componentDidMount, or elsewhere in the lifecycle (although also I understand the desire to stick with Stateless Functional Compeonents!)
You can still use Redux and mapDispatchToProps to inject the action creator into your comptonent, so your component is still only loosely connected to Redux.
This is my handle loggedIn. react-router v4
PrivateRoute is allow enter path if user is loggedIn and save the token to localStorge
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props => (localStorage.token) ? <Component {...props} /> : (
<Redirect
to={{
pathname: '/signin',
state: { from: props.location },
}}
/>
)
}
/>
);
}
Define all paths in your app in here
export default (
<main>
<Switch>
<Route exact path="/signin" component={SignIn} />
<Route exact path="/signup" component={SignUp} />
<PrivateRoute path="/" component={Home} />
</Switch>
</main>
);
Those who are facing issues in implementing this on react-router v4. Here is a working solution for navigating through the react app programmatically.
history.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
App.js OR Route.jsx. Pass history as a prop to your Router.
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
You can use push() to navigate.
import history from './history'
...
render() {
if (isLoggedIn) {
history.push('/test') // this should change the url and re-render Test component
}
// return login component
<Login />
}
All thanks to this comment: https://github.com/ReactTraining/react-router/issues/3498#issuecomment-301057248
render(){
return (
<div>
{ this.props.redirect ? <Redirect to="/" /> :'' }
<div>
add here component codes
</div>
</div>
);
}
I would suggest you to use connected-react-router https://github.com/supasate/connected-react-router
which helps to perform navigation even from reducers/actions if you want.
it is well documented and easy to configure
I was able to use history within stateless functional component, using withRouter following way (needed to ignore typescript warning):
import { withRouter } from 'react-router-dom';
...
type Props = { myProp: boolean };
// #ts-ignore
export const MyComponent: FC<Props> = withRouter(({ myProp, history }) => {
...
})
import { useNavigate } from "react-router-dom"; //with v6
export default function Component() {
const navigate = useNavigate();
navigate.push('/path');
}
I had this issue and just solved it with the new useNavigate hook in version 6 of react-router-dom

Categories

Resources