如何从Redux中的操作事件重定向

时间:2019-01-04 09:54:03

标签: javascript reactjs react-redux

我想在触发操作后重定向客户端。我听说过react-redux-router,但不确定如何在动作函数中正确实现它。

我遵循了这一点

https://stackoverflow.com/a/42985875/10865515

但是,当我提交经过验证的表单时,它不会重定向或刷新。

Actions.js

 import { auth as firebaseAuth } from '../firebaseConfig'
 import { push,  browserHistory } from 'react-router-redux';


 export const signUp = (user) => { return (dispatch) => {
  firebaseAuth.createUserWithEmailAndPassword(user.email, user.password)
    .then(() => {
        dispatch({ type: 'SIGNUP_SUCCESS',
        payload: (action, state, res) => {
            return res.json().then(json => {
              browserHistory.push('/');
              return json;
            });
          },
    });
    }).catch((err) => {
        dispatch({ type: 'SIGNUP_ERROR', err});
    });
  }  
}

Reducers.js

const initialState = {
  emailSignUp: '',
  passwordSignUp: '',
  authError: null

}

export default (state = initialState, action) => {
  switch (action.type) {
    case 'SIGNUP_SUCCESS':      
        return ({
            ...state,
            authError: null
        })

    case 'SIGNUP_ERROR':
        console.log('signup error')
        return ({
            ...state,
            authError: action.err.message
        })
    default:
        return state
 }
} 

Register.js

// ...
handleSubmit(event) {
    event.preventDefault();

    const {formData, errors} = this.state;
    const {email, password} = formData;

    const myError = this.props.authError;
    const creds = {
        email,
        password
    }
    const register = this.props.signUp(creds);
    if (register) {
        console.log(creds);

    }
}

3 个答案:

答案 0 :(得分:1)

您应该实现react-router-dom库,该库使您可以访问history对象进行导航。

在触发动作创建者的组件中:

import { withRouter } from "react-router-dom"

然后在代码底部,您将其称为connect:

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(myComponent))

现在,您可以将动作创建者设置为以历史为依据。

您的操作文件:

const signUp = (creds, history) => {
//do some logic then go home
   history.push("/")
}

因此,在您的事件处理程序中(您将其称为动作创建者),传递历史记录:

handleSubmit(event) {
    event.preventDefault();

    this.props.signUp(creds, this.props.history);
    if (register) {
        console.log(creds);
    }
}

答案 1 :(得分:0)

这是我关于firebase和redux的示例:

在您的动作内部,创建用户并将适当的动作分配给减速器:

export const signUp = newUser => {
  return (dispatch, getState, { getFirebase, getFirestore }) => {
    const firebase = getFirebase();
    const firestore = getFirestore();

    firebase
      .auth()
      .createUserWithEmailAndPassword(newUser.email, newUser.password)
      .then(resp => {
        return firestore
          .collection('users')
          .doc(resp.user.uid)
          .set({
            firstName: newUser.firstName,
            lastName: newUser.lastName
          });
      })
      .then(() => {
        dispatch({ type: 'SIGNUP_SUCCESS' });
      })
      .catch(err => {
        dispatch({ type: 'SIGNUP_ERROR', err });
      });
  };
};

在您的减速器中,您可以处理状态更改:

    case 'SIGNUP_SUCCESS':
        return {
            ...state,
            authError: null
        };
    case 'SIGNUP_ERROR':
        return {
            ...state,
            authError: action.err.message
        };

在组件中,您从Redirect导入react-router-dom并在成功注册后重定向:

    import { Redirect } from 'react-router-dom';

    class SignIn extends Component {
        state = {
            email: '',
            password: ''
        };
        handleChange = e => {
            this.setState({
                [e.target.id]: e.target.value
            });
        };
        handleSubmit = e => {
            e.preventDefault();
            this.props.signIn(this.state);
        };
        render() {
            const { authError, auth } = this.props;
            if (auth.uid) return <Redirect to="/" />;
            return (
                <div className="container">
                    <form onSubmit={this.handleSubmit} className="white">
                     ...
                    </form>
                </div>
            );
        }
    }

    const mapStateToProps = state => {
        return {
            authError: state.auth.authError,
            auth: state.firebase.auth
        };
    };

    const mapDispatchToProps = dispatch => {
        return {
            signIn: creds => dispatch(signIn(creds))
        };
    };

    export default connect(
        mapStateToProps,
        mapDispatchToProps
    )(SignIn);

答案 2 :(得分:0)

我修复了。

部分问题源自此

React history.push() is updating url but not navigating to it in browser

并且不知道如何正确使用then

我需要在应用程序周围包裹路由器标签

import App from './App';
import * as serviceWorker from './serviceWorker';
import { createStore, applyMiddleware, compose } from 'redux'
import { Provider } from 'react-redux';
import rootReducer from './reducers';
import thunk from 'redux-thunk'
import { BrowserRouter as Router } from 'react-router-dom';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);

ReactDOM.render(
    <Provider store={createStoreWithMiddleware(rootReducer)}>
     <Router >
      <App />
      </Router>
    </Provider>

    ,document.getElementById('root'));

并像这样更新我的动作

import { push } from 'react-router-redux';
import { history } from '../components/Navbar';

export const signUp = (user) => { return (dispatch) => {
    firebaseAuth.createUserWithEmailAndPassword(user.email, user.password)
        .then(() => {
            dispatch({ type: 'SIGNUP_SUCCESS' })
        }).then((response) => {
            history.push('/');
        }).catch((err) => {
            dispatch({ type: 'SIGNUP_ERROR', err});
        });


    }

}

Navbar.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import createBrowserHistory from 'history/createBrowserHistory';
import SignUp from './SignUp';
import SignIn from './SignIn';
// forcerefresh does the magic.
export const history = createBrowserHistory({forceRefresh:true});

const Navbar = () => {
    return(

    <Router history={history}>
        <div>
        <nav className="navbar navbar-expand-lg navbar-light bg-light ">
          <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample08" aria-controls="navbarsExample08" aria-expanded="false" aria-label="Toggle navigation">
            <span className="navbar-toggler-icon"></span>
          </button>

          <div className="collapse navbar-collapse justify-content-md-center" id="navbarsExample08">
            <ul className="navbar-nav">

                <li className="nav-item">
                    <Link className="nav-link" to="/">Home </Link>
                </li>
                <li className="nav-item">
                    <Link className="nav-link" to="/SignUp">Sign Up </Link>
                </li>
                <li className="nav-item">
                    <Link  className="nav-link" to="/SignIn">Sign In </Link>
                </li>


            </ul>
          </div>
        </nav>
        <Route path="/SignUp" component={SignUp} />
        <Route path="/SignIn" component={SignIn} />
        <Route path="/"/>


    </div>
    </Router>
    );

}

export default Navbar;

保持现有的handleSubmit函数不变。