I have this class:
export default class Panel extends PureComponent {
constructor(props){
super(props);
this.state = {
loading: true,
url: '/' +this.props.lang+ '/panel',
about: '/' +this.props.lang+ '/panel' + '/about',
user: '/' +this.props.lang+ '/panel' + '/user/1',
userPath: '/' +this.props.lang+ '/panel' + '/user/:id'
}
}
componentDidMount(){
this.setState({
loading: false
});
console.log(this.state.user);
}
onResize(width){
var totalWidth = width + 250 + "px";
var contentWidth = width + "px";
document.querySelector('.panel__slideContainer').style.width = totalWidth;
document.querySelector('.mainContainer').style.width = contentWidth;
}
render() {
if(this.state.loading === true){
return <p>Loading...</p>
}
return (
<div className="container panel__container">
<Router>
<ReactResizeDetector handleWidth onResize={this.onResize} />
<div className="panel__slideContainer">
<nav className="panel__sideMenu">
<ul>
<li>
<NavLink exact activeClassName="active" to={this.state.url}>Home</NavLink>
</li>
<li>
<NavLink activeClassName="active" to={this.state.about}><Trans>change password</Trans></NavLink>
</li>
<li>
<NavLink activeClassName="active" to="/pl/panel/user/1">User</NavLink>
</li>
</ul>
</nav>
<div className="mainContainer">
<Nav />
<div>
<Switch>
<Route exact path={this.state.url}>
<Home />
</Route>
<Route path={this.state.about} >
<About />
</Route>
<Route path="/pl/panel/user/:id">
<User />
</Route>
</Switch>
</div>
</div>
</div>
</Router>
</div>
);
}
}
I have a problem with User component which not read a props. Before I tried display route without <Switch>
like this:
<Route path="" component={} />
and after click component was loaded correctly and display props but after refresh website it display me error 404. After implement Switch, it absolutely broken. Nothing display (only error with console log)
// This is the error:
> Cannot read property 'params' of undefined
> backend.js:6 The above error occurred in the <User> component:
> Uncaught TypeError: Cannot read property 'params' of undefined
@Edit User component import React from 'react';
const User = (props) => {
return (
<div>
<p>User id: {props.match.params.id}</p>
</div>
);
}
export default User;
Any idea how I can solve my problem?
This error is caused by the match
prop being undefined in the <User/>
component, when the "/pl/panel/user/:id"
route is matched which in turn means an exception is thrown when params.id
is accessed.
There are a few solutions to resolve this - a simple fix is to specify the User
component at it's particular <Route/>
via the component
prop:
<Route path="/pl/panel/user/:id" component={User} />
By specifying the User
component in this way, react-router will automatically inject the match
prop into User
when the route is matched and the component is renderered.
Another option is to use the withRouter
:
import { withRouter } from "react-router-dom";
/* Your current User component left as is */
const User = (props) => { ... }
/* Router injected into User */
const UserWithRouter = withRouter(User);
<Route path="/pl/panel/user/:id">
{/* Use UserWithRouter instead, match will now be defined in User */}
<UserWithRouter />
</Route>
The withRouter
HOC has the same effect as the first approach, causing the match
prop to be injected into the target component (ie User
) when the UserWithRouter
component is rendered.
The 404 error that you're seeing when refreshing the browser is likely due to inconsistent client side and server side routing.
For example, navigating to a route /pl/panel/user/1
on the client and then refreshing the page will issue a request to your server for the resource at /pl/panel/user/1
. Because the server doesn't know how to handle that, a 404 will typically be returned.
A simple fix would be to replace <BrowserRouter>
with <HashRouter>
in your client side code. This will prefix your url path with an #
, however it will allow the reloading behavior you require without the need for any changes to your backend.
Hope that helps!