Reputation: 1408
I have a strange problem with rendering a component while Route changes. Versions I use
{
"react": "16.9.0",
"react-dom": "16.9.0",
"react-router-dom": "5.1.0"
}
This is my route configuration
const Routes = () => {
const isLoggedIn = StorageManager.get('session');
return (
<>
<div className="background"></div>
<MainLayout>
<Header />
<LeftSidebarMenu />
<main className="main-container">
<Router history={history}>
<Switch>
<Redirect exact from="/" to="/categories" />
<Route exact path='/categories' component={Home} />
<Route exact path='/categories/new' component={CreateCategory} />
<Route exact path='/login' component={Login}
/>
</Switch>
</Router>
</main>
</MainLayout>
</>
);
};
export default Routes;
The main problem is that, when a user clicks login/logout, in case of success/failure, it should redirect the user to the appropriate page. Actually the route changes, but the component doesn't get rendered. I use history.push(PATH) for redirecting users. I am not a beginner in react and to be honest, the first time I am faced with this kind of strange problem. Maybe I confused something with my router configs.
import React, {useState} from 'react';
import {withRouter, Link} from 'react-router-dom';
import Modal from 'react-modal';
import {shallowEqual, useSelector} from 'react-redux';
import Button from '../../components/core/button';
import StorageManager from '../../helpers/utilities/storageManager';
import FormGroup from '../../components/core/form/form-group';
import useForm from '../../helpers/custom-hooks';
import {signInRequest} from '../../redux/actions';
Modal.setAppElement('#root');
const Header = (props) => {
const actionResult = useSelector((state) => state.admin.actionResult, shallowEqual);
const {handleInputChange, handleSubmit} = useForm(signInRequest);
const [session, setSession] = useState(StorageManager.get('session'));
const [isLoginModalOpen, toggleLoginModal] = useState(false);
const toggleModal = () => toggleLoginModal(!isLoginModalOpen);
const handleLogin = () => {
handleSubmit();
};
if(actionResult && actionResult.type === 'success' && isLoginModalOpen){
setSession(StorageManager.get('session'));
toggleLoginModal(false);
props.history.push('/categories');
}
const handleLogout = () => {
props.history.push('/login');
StorageManager.remove('session');
// setSession('');
};
return (
<header className="header-section clearfix">
<div className="header-container">
<div className="header-left-menu">
<div className='header-logo-box'>
<a className="navbar-brand" href="#"><img src={require('../../images/logo.png')} alt=""/></a>
</div>
</div>
<Link to='/categories'>Link</Link>
<div className="header-right-menu">
<div className="user-settings">
<img src={require('../../images/user.png')} alt=""/>
<span>Username</span>
{
session ?
<Button
className='btn-medium'
text='Выход'
onClick={handleLogout}
/> :
<Button
className='btn-medium'
text='Логин'
onClick={toggleModal}
/>
}
</div>
</div>
</div>
<Modal
isOpen={isLoginModalOpen}
style={customStyles}
shouldCloseOnOverlayClick={true}
onRequestClose={toggleModal}
contentLabel="Login Modal"
>
<FormGroup className='form-group__modal'>
<h3>Login</h3>
<input
type="text"
placeholder="login"
name="login"
className='form-input'
onChange={handleInputChange}
/>
<h3>Password</h3>
<input
type="text"
placeholder="password"
name="password"
className='form-input'
onChange={handleInputChange}
/>
<Button
text='Sign in'
onClick={handleLogin}
/>
<div className='invalid'>{actionResult ? actionResult.message : ''}</div>
</FormGroup>
</Modal>
</header>
);
};
export default withRouter(Header);
Upvotes: 2
Views: 3231
Reputation: 281686
The problem in your code is that the place where you wish to take an action is not wrapped by a Router provider. Even if you use withRouter which is an HOC that tried to get the router props from the nearest provider of Routes, it won't get you the history props from your Router that is used to wrap all your Routes.
You need to update how you wrap your components with Router like
const Routes = () => {
const isLoggedIn = StorageManager.get('session');
return (
<>
<div className="background"></div>
<Router history={history}>
<MainLayout>
<Header />
<LeftSidebarMenu />
<main className="main-container">
<Switch>
<Redirect exact from="/" to="/categories" />
<Route exact path='/categories' component={Home} />
<Route exact path='/categories/new' component={CreateCategory} />
<Route exact path='/login' component={Login}
/>
</Switch>
</main>
</MainLayout>
</Router>
</>
);
};
export default Routes;
Upvotes: 4