Reagiere Router-Umleitung nach Aktion Redux


72

Ich verwende React-Redux und Standard-React-Routing. Ich muss nach einer bestimmten Aktion umleiten.

Zum Beispiel: Ich habe einige Schritte Registrierung. Und nach der Aktion:

function registerStep1Success(object) {
    return {
        type: REGISTER_STEP1_SUCCESS,
        status: object.status
   };
}

Ich möchte, dass er zur Seite mit der RegistrierungSchritt2 weiterleitet. Wie es geht?

ps Im Verlaufsbrowser war '/ registerStep2' noch nie. Diese Seite wird erst nach erfolgreicher Ergebnisregistrierung angezeigt.


Antworten:


63

Mit React Router 2+ können Sie überall dort, wo Sie die Aktion auslösen, anrufen browserHistory.push()(oder hashHistory.push()wenn Sie dies verwenden):

import { browserHistory } from 'react-router'

// ...
this.props.dispatch(registerStep1Success())
browserHistory.push('/registrationStep2')

Sie können dies auch von asynchronen Aktionserstellern tun, wenn Sie dies verwenden.


1
Was sind die Vorteile von Redux-Router in Zukunft, die jetzt in der Beta sind?
Ximet

6
Wenn Sie möchten, dass Redux DevTools Routing-Übergänge wiedergibt, müssen Sie zwischen github.com/acdlite/redux-router und github.com/reactjs/react-router-redux wählen . In diesem Fall würde ich github.com/reactjs/react-router-redux empfehlen, da es stabiler und viel einfacher ist.
Dan Abramov

2
Ist diese Lösung noch verfügbar? Ich scheine nicht in der Lage zu sein, dies zum Laufen zu bringen ... Die URL wird aktualisiert, nachdem ich sie verwendet habe browserHistory.push(), die Ansicht jedoch nicht.
Vasekhlav

1
Egal, ich habe es zum Laufen gebracht, ich habe es benutzt, browserHistory.push()obwohl mein Router es benutzt hat hashHistory. hashHistory.push()klappt wunderbar.
Vasekhlav

14
Gilt dies immer noch für React Router 4+? Oder gibt es jetzt einen besseren Weg, dies zu tun?
Jörg

24

Haben Sie React -Router-Redux ausgecheckt ? Diese Bibliothek ermöglicht die Synchronisierung des React-Routers mit Redux.

Hier ist ein Beispiel aus der Dokumentation, wie Sie die Umleitung mit einer Push-Aktion von React-Router-Redux implementieren können.

import { routerMiddleware, push } from 'react-router-redux'

// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)

// Dispatch from anywhere like normal.
store.dispatch(push('/foo'))

Ich weiß davon Routing. Aber ich frage mich,
ob

19
Und wie auf der anderen Seite nach Aktion umleiten (mit React-Router-Redux)?
Ximet

Können Sie auf das Geschäft im Reduzierstück zugreifen?
Ante

6
React-Router-Redux ist jetzt veraltet. Werfen Sie stattdessen einen Blick auf github.com/supasate/connected-react-router
Uj Corb

7

Einfachste Lösung für Router Version 4+: Wir verwenden "React-Router-Dom": "4.3.1" Es funktioniert nicht mit Version 5+

Exportieren Sie Ihren Browserverlauf von der Stelle, an der er initialisiert wurde, und verwenden Sie browserHistory.push ('/ pathToRedirect'):

Der Paketverlauf muss installiert sein (Beispiel: "Verlauf": "4.7.2"):

npm install --save history

In meinem Projekt initialisiere ich den Browserverlauf in index.js:

import { createBrowserHistory } from 'history';

export const browserHistory = createBrowserHistory();

Weiterleiten in der Aktion:

export const actionName = () => (dispatch) => {
    axios
            .post('URL', {body})
            .then(response => {
                // Process success code
                  dispatch(
                    {
                      type: ACTION_TYPE_NAME,
                      payload: payload
                    }
                  );
                }
            })
            .then(() => {
                browserHistory.push('/pathToRedirect')
            })
            .catch(err => {
                // Process error code
                    }
                );
            });
};

Es ändert urlzwar den "React-Router", hat aber keine Auswirkungen darauf. Wenn Sie dieses Modul verwenden, rate ich Ihnen, nach einer anderen Lösung zu suchen.
YanivGK

Diese Lösung funktioniert immer noch perfekt, aber es gibt noch viele andere.
Jackkobec

Verwenden Sie für diese Lösung "react-router-dom": "4+". Wir verwenden "
React

Ich habe es gerade noch einmal versucht, wird immer noch nicht funktionieren. Ich benutze tatsächlich "react-router-dom": "5.2.0", obwohl die urlÄnderungen der Browser nicht auf die gewünschte Seite surfen. Ich denke, ich könnte eine andere Frage aufwerfen, das scheint seltsam.
YanivGK

1
Diese Lösung funktioniert nicht mit Router v5. Verwenden Sie für diese Lösung "react-router-dom": "4+". Wir verwenden "
React

4

Um auf den vorherigen Antworten von Eni Arinde aufzubauen (ich habe nicht den Ruf zu kommentieren), verwenden Sie die folgende store.dispatchMethode nach einer asynchronen Aktion:

export function myAction(data) {
    return (dispatch) => {
        dispatch({
            type: ACTION_TYPE,
            data,
        }).then((response) => {
            dispatch(push('/my_url'));
        });
    };
}

Der Trick besteht darin, dies in den Aktionsdateien und nicht in den Reduzierern zu tun, da Reduzierungen keine Nebenwirkungen haben sollten.


1
Selbst wenn diese Lösung funktioniert, sollten Aktionen IMO überhaupt nicht über das Routing informiert sein. Sie sollten in der Lage sein, eine Aktion ohne Routing auszulösen.
Winterzähler

Ist dies ein richtiger Weg, um das Problem anzugehen? Sollten wir das Verlaufsobjekt von der Komponente zum Weiterleiten an den Aktionsersteller übergeben?
Jitin Maherchandani


2
Wie können Sie Versandanrufe verketten? dispatch (). then (() => dispatch)? Es scheint nicht zu funktionieren. 'dann ist keine Funktion'
Nour

3

Sie können { withRouter } von 'react-router-dom' verwenden.

Das folgende Beispiel zeigt einen Versand zum Pushen

export const registerUser = (userData, history) => {
  return dispatch => {
    axios
    .post('/api/users/register', userData)
    .then(response => history.push('/login'))
    .catch(err => dispatch(getErrors(err.response.data)));
  }
}

Die Verlaufsargumente werden in der Komponente als zweiter Parameter dem Aktionsersteller zugewiesen (in diesem Fall 'registerUser').


Könnten Sie bitte den relevanten importsund den Rest des Codes teilen ?
YanivGK

0

Hier ist die Arbeitskopie von Routing - App

    import {history, config} from '../../utils'
        import React, { Component } from 'react'
        import { Provider } from 'react-redux'
        import { createStore, applyMiddleware } from 'redux'
        import Login from './components/Login/Login';
        import Home from './components/Home/Home';
        import reducers from './reducers'
        import thunk from 'redux-thunk'

        import {Router, Route} from 'react-router-dom'

        import { history } from './utils';

        const store = createStore(reducers, applyMiddleware(thunk))



        export default class App extends Component {
          constructor(props) {
            super(props);

            history.listen((location, action) => {
              // clear alert on location change
              //dispatch(alertActions.clear());
            });
          }
          render() {
            return (
              <Provider store={store}>
                <Router history={history}>
                  <div>
                    <Route exact path="/" component={Home} />
                    <Route path="/login" component={Login} />
                  </div>
                </Router>
              </Provider>
            );
          }
        }

export const config = {
    apiUrl: 'http://localhost:61439/api'
};
import { createBrowserHistory } from 'history';

    export const history = createBrowserHistory();
//index.js
export * from './config';
export * from './history';
export * from './Base64';
export * from './authHeader';

import { SHOW_LOADER, AUTH_LOGIN, AUTH_FAIL, ERROR, AuthConstants } from './action_types'

import Base64 from "../utils/Base64";

import axios from 'axios';
import {history, config, authHeader} from '../utils'
import axiosWithSecurityTokens from '../utils/setAuthToken'


export function SingIn(username, password){


    return async (dispatch) => {
      if(username == "gmail"){
        onSuccess({username:"Gmail"}, dispatch);
      }else{
      dispatch({type:SHOW_LOADER, payload:true})
        let auth = {
            headers: {
              Authorization: 'Bearer ' + Base64.btoa(username + ":" + password)
            }
          }
        const result = await axios.post(config.apiUrl + "/Auth/Authenticate", {}, auth);
        localStorage.setItem('user', result.data)
        onSuccess(result.data, dispatch);
    }
  }

}

export function GetUsers(){
  return async (dispatch) => {
var access_token = localStorage.getItem('userToken');
    axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}` 

    var auth = {
      headers: authHeader()
    }
    debugger
      const result = await axios.get(config.apiUrl + "/Values", auth);
      onSuccess(result, dispatch);
      dispatch({type:AuthConstants.GETALL_REQUEST, payload:result.data})
  }
}



const onSuccess = (data, dispatch) => {

  const {username} = data;
  //console.log(response);
  if(username){
    dispatch({type:AuthConstants.LOGIN_SUCCESS, payload: {Username:username }});
    history.push('/');
    // Actions.DashboardPage();
  }else{
    dispatch({ type: AUTH_FAIL, payload: "Kullanici bilgileri bulunamadi" });
  }
  dispatch({ type: SHOW_LOADER, payload: false });
}
const onError = (err, dispatch) => {
  dispatch({ type: ERROR, payload: err.response.data });
  dispatch({ type: SHOW_LOADER, payload: false });
}

export const SingInWithGmail = () => {
  return { type :AuthConstants.LOGIN_SUCCESS}
}

export const SignOutGmail = () => {
  return { type :AuthConstants.LOGOUT}
}

0
signup = e => {
  e.preventDefault();
  const { username, fullname, email, password } = e.target.elements,
    { dispatch, history } = this.props,
    payload = {
      username: username.value,
      //...<payload> details here
    };
  dispatch(userSignup(payload, history));
  // then in the actions use history.push('/<route>') after actions or promises resolved.
};

render() {
  return (
    <SignupForm onSubmit={this.signup} />
    //... more <jsx/>
  )
}

0

Eine aktualisierte Antwort mit Hooks; für Router v5 Benutzer.

Arbeiten an react-router-dom:5.1.2.

Es ist keine Installation eines externen Pakets erforderlich.

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

Du kannst den ... benutzen history wie Sie es bisher gewohnt sind.

Weitere Details und APIs - lesen Sie das Handbuch

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.