【问题标题】:React router redirect after action redux动作redux后反应路由器重定向
【发布时间】:2016-06-12 22:07:46
【问题描述】:

我正在使用react-reduxreact-router。我需要在发送操作后重定向。

例如:我已经注册了几步。行动后:

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

我想重定向到带有registrationStep2的页面。我该怎么做?

附言在历史浏览器中“/registrationStep2”尚未被访问。该页面只有在结果注册成功Step1页面后才会出现。

【问题讨论】:

标签: reactjs react-router redux redux-framework


【解决方案1】:

在使用 react-router-dom 版本 +5 时,您不能在 redux(redux 工具包)中使用 useHistory 钩子。

因此,如果您想在发送操作后重定向,您可以在当前页面(组件)中“通过 useHistory() 钩子”获取您的历史记录,然后将历史记录与您的有效负载一起作为redux 的论据。 因此,您可以在像这样发送操作后轻松地在 redux 中管理您的历史记录: history.push ("某处)

【讨论】:

    【解决方案2】:

    我们可以使用“connected-react-router”。

        import axios from "axios";
        import { push } from "connected-react-router";
        
        export myFunction = () => {
          return async (dispatch) => {
            try {
              dispatch({ type: "GET_DATA_REQUEST" });
              const { data } = await axios.get("URL");
              dispatch({
                type: "GET_DATA_SUCCESS",
                payload: data
              });
            } catch (error) {
              dispatch({
                type: "GET_DATA_FAIL",
                payload: error,
              });
              dispatch(push("/notfound"));
            }
          };
        };
    

    注意--请先到https://github.com/supasate/connected-react-router阅读文档并设置connected-react-router,然后使用connected-react-router中的“推送”。

    【讨论】:

      【解决方案3】:

      使用钩子的更新答案;适用于路由器 v5 用户。

      正在处理react-router-dom:5.1.2

      不需要安装外部包。

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

      您可以像以前一样使用history

      更多详情和 API - 阅读manual

      【讨论】:

        【解决方案4】:

        路由器版本 4+ 的最简单解决方案: 我们使用“react-router-dom”:“4.3.1” 它不适用于版本 5+

        从初始化位置导出浏览器历史记录 并使用 browserHistory.push('/pathToRedirect'):

        必须安装包历史记录(例如:“history”:“4.7.2”):

        npm install --save history
        

        在我的项目中,我在 index.js 中初始化浏览器历史记录:

        import { createBrowserHistory } from 'history';
        
        export const browserHistory = createBrowserHistory();
        

        在动作中重定向:

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

        【讨论】:

        • 它确实改变了url,但不影响'react-router'。如果您正在使用此模块 - 我建议您寻找不同的解决方案。
        • 这个解决方案仍然完美,但还有很多其他的。
        • 对这个解决方案使用 "react-router-dom": "4+"。我们使用“react-router-dom”:“4.3.1”
        • 我刚刚又试了一次,还是不行。我实际上使用"react-router-dom": "5.2.0",即使url 更改浏览器不会冲浪到所需的页面。我想我可能会提出一个不同的问题,这看起来很奇怪。
        • 此解决方案不适用于路由器 v5。使用 "react-router-dom": "4+" 作为这个解决方案。我们使用“react-router-dom”:“4.3.1
        【解决方案5】:
        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/>
          )
        }
        

        【讨论】:

          【解决方案6】:

          这是路由应用程序的工作copy

              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}
          }
          

          【讨论】:

            【解决方案7】:

            您可以使用“react-router-dom”中的 {withRouter}

            下面的示例演示了要推送的调度

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

            历史参数在组件中作为第二个参数分配给操作创建者(在本例中为“registerUser”)

            【讨论】:

            • 能否分享一下相关的imports,以及剩下的代码?
            【解决方案8】:

            以 Eni Arinde 先前的回答为基础(我没有评论的声誉),这里是如何在异步操作后使用 store.dispatch 方法:

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

            诀窍是在动作文件中而不是在减速器中进行,因为减速器不应该有副作用。

            【讨论】:

            • 即使此解决方案有效,操作也不应完全了解 IMO 路由。您应该能够在没有任何路由的情况下调度操作。
            • 这是解决问题的正确方法吗?我们是否应该将历史对象从组件传递给动作创建者进行路由?
            • 如何链接调度调用? dispatch().then(()=>dispatch) ?它似乎不起作用。 'then 不是函数'
            【解决方案9】:

            使用 React Router 2+,无论您在哪里调度操作,都可以调用 browserHistory.push()(或 hashHistory.push(),如果您使用的是):

            import { browserHistory } from 'react-router'
            
            // ...
            this.props.dispatch(registerStep1Success())
            browserHistory.push('/registrationStep2')
            

            如果您使用的是异步操作创建者,您也可以这样做。

            【讨论】:

            • 未来使用 redux-router 有什么好处,现在是 beta 版?
            • 如果你想要 Redux DevTools 重放路由转换,你需要在 github.com/acdlite/redux-routergithub.com/reactjs/react-router-redux 之间进行选择。在这种情况下,我会推荐github.com/reactjs/react-router-redux,因为它更稳定、更简单。
            • 此解决方案是否仍然可用?我似乎无法正常工作...在我使用 browserHistory.push() 后 URL 会更新,但视图不会。
            • 没关系,我搞定了,我使用的是browserHistory.push(),虽然我的路由器使用的是hashHistoryhashHistory.push() 就像一个魅力。
            • 这对于 React Router 4+ 仍然适用吗?还是现在有更好的方法来做到这一点?
            【解决方案10】:

            您查看react-router-redux 了吗?这个库使 react-router 与 redux 同步成为可能。

            这是文档中的一个示例,说明如何使用 react-router-redux 的推送操作实现重定向。

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

            【讨论】:

            • 我知道它的路由。但是,我想知道是否可以使用标准的反应路由
            • 以及Action之后如何重定向到其他页面(使用react-router-redux)。?
            • 你能访问reducer里面的store吗?
            • react-router-redux in 现在已弃用。看看github.com/supasate/connected-react-router
            猜你喜欢
            • 2019-12-30
            • 2019-10-03
            • 2016-03-11
            • 1970-01-01
            • 2018-04-01
            • 2019-01-19
            • 2016-11-27
            • 2022-08-19
            相关资源
            最近更新 更多