URL изменяется, но новая страница страницы не отображается Ionic React, IonReactRouter с историей

Я пишу приложение с использованием Ionic 5 с React и Redux. Я пытаюсь перейти на новую страницу / tabs / home после успешной попытки входа в систему. Я пытаюсь сделать это, вставив новый URL-адрес в опору истории реактивного маршрутизатора, когда я получаю успешный ответ от бэкэнда. Это работает тем, что он меняет URL-адрес с / login на / tabs / home, но страница входа по-прежнему отображается.

index.tsx

import React from 'react';
import {render} from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './helpers/store';
import { Router } from 'react-router';
import CreateBrowserHistory from 'history/createBrowserHistory';

export const history = CreateBrowserHistory();

render(
    <Provider store={store}>
        <Router history={history}>
             <App />           
        </Router>
    </Provider>,
    document.getElementById('root')
);

App.tsx

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { history } from './index';
import { alertActions } from './actions/alert.actions';
import { Route } from 'react-router-dom';
import {
  IonApp,
} from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { LoginPage } from './pages/Login';

import MainTabs from './pages/MainTabs';

function App() {
  const alert = useSelector(state => state.alert);
  const dispatch = useDispatch();

  useEffect(() => {
    history.listen((location, action) => {
      console.log(location);
      console.log(action);
      dispatch(alertActions.clear());
    });
  }, []);

  return (
    <IonApp>
        {/*
         // @ts-ignore*/}
        <IonReactRouter history={history}>
          <Route path="/tabs" component={MainTabs} />
          <Route path="/login" component={LoginPage} />
        </IonReactRouter>
    </IonApp>
  )
}

export default App;

Login.tsx

function LoginPage() {
  const [inputs, setInputs] = useState({
    username: '',
    password: ''
  });
  const [submitted, setSubmitted] = useState(false);
  const { username, password } = inputs;
  const loggingIn = useSelector(state => state.authentication.loggingIn);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(userActions.logout());
  }, []);

  function handleChange(e) {
    const { name, value } = e.target;
    setInputs(inputs => ({ ...inputs, [name]: value }));
  }

  function handleSubmit(e) {
     e.preventDefault();

     setSubmitted(true);
     if (username && password) {
       dispatch(userActions.login(username, password));
     }
  }

  return (
    <IonPage id="login-page">
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonMenuButton></IonMenuButton>
          </IonButtons>
          <IonTitle>Login</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>

        <form noValidate onSubmit={handleSubmit}>
          <IonList>
            <IonItem>
              <IonLabel position="stacked" color="primary">Username</IonLabel>
              <IonInput name="username" type="text" value={username} spellCheck={false} autocapitalize="off" onIonChange={handleChange} className={'form-control' + (submitted && !username ? ' is-invalid' : '')} required>
              </IonInput>
            </IonItem>

            <IonItem>
              <IonLabel position="stacked" color="primary">Password</IonLabel>
              <IonInput name="password" type="password" value={password} onIonChange={handleChange} className={'form-control' + (submitted && !password ? ' is-invalid' : '')} required>
              </IonInput>
            </IonItem>

          </IonList>

          <IonRow>
            <IonCol>
              {loggingIn && <span className="spinner-border spinner-border-sm mr-1"></span>}
              <IonButton type="submit" expand="block">Login</IonButton>
            </IonCol>
            <IonCol>
              <IonButton routerLink="/signup" color="light" expand="block">Signup</IonButton>
            </IonCol>
          </IonRow>
        </form>

      </IonContent>

    </IonPage>
  )
}

export { LoginPage };

действие входа

function login(username, password) {
    return dispatch => {
        dispatch(request({ username }));

        userService.login(username, password)
        .then(
            user => {
                dispatch(success(user));
                history.push('/tabs/home');
            },
            error => {
                dispatch(failure(error.toString()));
                dispatch(alertActions.error(error.toString()));
            }
        );
    };

    function request(user) { return { type: userConstants.LOGIN_REQUEST, user } }
    function success(user) { return { type: userConstants.LOGIN_SUCCESS, user } }
    function failure(error) { return { type: userConstants.LOGIN_FAILURE, error } }
}

3 ответа

Решение

ВЫПУСК:

Согласно документу:

В IonReactRouter компонент обертывает традиционный BrowserRouterкомпонент из React Router и настраивает приложение для маршрутизации. Поэтому используйтеIonReactRouter на месте BrowserRouter. Вы можете передать любой реквизит вIonReactRouter и они будут переданы нижестоящему BrowserRouter.

Я думаю обычай history не поддерживается BrowserRouter, как вы видете BrowserRouter поддерживает этот реквизит, там нет history реквизит там

basename
forceRefresh
getUserConfirmation
keyLength
children

history реквизит доступен для Router

Проблема на гитхабе


РЕШЕНИЕ:

Итак, я внес ниже изменения для использования пользовательской истории, и она работает


index.js

import React from "react";
import { render } from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import { store } from "./helpers/store";

render(
  <Provider store={store}>
      <App />
  </Provider>,
  document.getElementById("root")
);

App.tsx

    <IonApp>
      <Router history={history}>
        {/* <IonReactRouter history={history}> */}
        <Route path="/tabs" component={MainTabs} />
        <Route exact path="/" component={LoginPage} />
        {/* </IonReactRouter> */}
      </Router>
    </IonApp>

ИЛИ

Вы можете использовать что-то вроде этого как hack, ref

import React from 'react'
import { History } from 'history'
import { useHistory } from 'react-router'

// Add custom property 'appHistory' to the global window object
declare global {
  interface Window { appHistory: History }
}

const MyApp: React.FC = () => {
  // Store the history object globally so we can access it outside of React components
  window.appHistory = useHistory()

  ...
}

Просто положите exact атрибут в Маршруте, чтобы решить эту

 <Route path="/tabs" exact component={MainTabs} />
 <Route path="/login" exact component={LoginPage} />

В вашем коде у вас есть

<Route path "/tabs" component={MainTabs} />

Когда вместо этого должно быть

<Route path "/tabs/home" component={MainTabs} />

Когда вы пытаетесь продвинуть свою историю с помощью /tabs/home для этого не указан маршрут, поэтому он не будет знать, куда идти.

Также в вашем индексном файле я бы порекомендовал иметь дополнительный маршрут вроде этого

<Route exact path "/tabs" component={SomeComponent} />
<Route path "/tabs/home" component={MainTabs} />

На всякий случай, если вы планируете привязать к вашему /tabs маршрут.

Другие вопросы по тегам