URL изменяется, но новая страница страницы не отображается Ioni c React, IonReactRouter с историей - PullRequest
1 голос
/ 17 июня 2020

Я пишу приложение, используя Ioni c 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 ]

1 голос
/ 19 июня 2020

В вашем коде

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

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

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

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

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

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

На всякий случай вы планируйте, чтобы к вашему маршруту /tabs было подключено более одного пути.

1 голос
/ 19 июня 2020

ПРОБЛЕМА:

Согласно do c:

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

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

basename
forceRefresh
getUserConfirmation
keyLength
children

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

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

РЕШЕНИЕ:

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

индекс. 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>

ИЛИ

Вы можете использовать что-то вроде этого как хак, 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()

  ...
}
1 голос
/ 18 июня 2020

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

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