I want to redirect the client after an action has been fired. I heard of react-redux-router
, but not sure how to properly implement it in the actions function.
i followed a little bit of this
However, when i submit the validated form, it doesn't redirect or refreshes.
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);
}
}
I want to redirect the client after an action has been fired. I heard of react-redux-router
, but not sure how to properly implement it in the actions function.
i followed a little bit of this
https://stackoverflow./a/42985875/10865515
However, when i submit the validated form, it doesn't redirect or refreshes.
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);
}
}
Share
Improve this question
asked Jan 4, 2019 at 9:54
Eric ThomasEric Thomas
211 gold badge2 silver badges6 bronze badges
1
- Maybe this post will help stackoverflow./questions/48514773/… – Shubham Khatri Commented Jan 4, 2019 at 10:39
3 Answers
Reset to default 6You should implement the react-router-dom
library which gives you access to the history
object for navigation.
In your ponent that is firing the action creator:
import { withRouter } from "react-router-dom"
Then at the bottom of the code, where you call connect:
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(myComponent))
Now you can set up your action creator to take in history as an argument.
Your actions file:
const signUp = (creds, history) => {
//do some logic then go home
history.push("/")
}
So in your event handler where you call your action creator, pass in history:
handleSubmit(event) {
event.preventDefault();
this.props.signUp(creds, this.props.history);
if (register) {
console.log(creds);
}
}
This is my example with firebase and redux:
Inside your actions you create the user and dispatch appropriate actions to your reducer:
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 });
});
};
};
In your reducer you handle the state change:
case 'SIGNUP_SUCCESS':
return {
...state,
authError: null
};
case 'SIGNUP_ERROR':
return {
...state,
authError: action.err.message
};
In the ponent you import Redirect
from react-router-dom
and redirect on successful signup:
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);
I fixed it.
Apart of the problem stemmed from this
React history.push() is updating url but not navigating to it in browser
and not knowing how to properly use then
I needed to wrap the router tags around the app
import App from './App';
import * as serviceWorker from './serviceWorker';
import { createStore, applyMiddleware, pose } 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'));
and update my actions like so
import { push } from 'react-router-redux';
import { history } from '../ponents/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" ponent={SignUp} />
<Route path="/SignIn" ponent={SignIn} />
<Route path="/"/>
</div>
</Router>
);
}
export default Navbar;
Keep my existing handleSubmit function the same.