React router перенаправляет страницу, но компонент не отображается - PullRequest
0 голосов
/ 08 ноября 2019

У меня странная проблема с рендерингом компонента при изменении маршрута. Версии, которые я использую

{
  "react": "16.9.0",
  "react-dom": "16.9.0",
  "react-router-dom": "5.1.0"
}

Это моя конфигурация маршрута

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;

Основная проблема заключается в том, что, когда пользователь нажимает на кнопку входа / выхода, в случае успеха / неудачи, он должен перенаправитьпользователь на соответствующую страницу. На самом деле маршрут меняется, но компонент не отображается. Я использую history.push (PATH) для перенаправления пользователей. Я не новичок в реакции и, честно говоря, впервые сталкиваюсь с такой странной проблемой. Может быть, я что-то перепутал с конфигами моего роутера.

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);

1 Ответ

4 голосов
/ 08 ноября 2019

Проблема в вашем коде заключается в том, что место, где вы хотите выполнить действие, не обернуто провайдером маршрутизатора. Даже если вы используете withRouter, который является HOC, который пытался получить реквизиты маршрутизатора от ближайшего провайдера маршрутов, он не получит вам реквизиты истории от вашего маршрутизатора, который используется для упаковки всех ваших маршрутов.

Вам необходимо обновить способ упаковки компонентов с помощью Router, например

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;
...