Norayr Ghukasyan
Norayr Ghukasyan

Reputation: 1408

React router redirects the page but component doesn't get rendered

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

Answers (1)

Shubham Khatri
Shubham Khatri

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

Related Questions