Как перенаправить с события действия в Redux - PullRequest
0 голосов
/ 04 января 2019

Я хочу перенаправить клиента после запуска действия. Я слышал о 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 голосов
/ 04 января 2019

Это мой пример с 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);
0 голосов
/ 05 января 2019

Я исправил это.

Помимо проблемы, связанной с этим

React history.push () обновляет URL, но не переходит на него в браузере

и не зная, как правильно использовать 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 такой же.

0 голосов
/ 04 января 2019

Вы должны реализовать библиотеку react-router-dom, которая дает вам доступ к объекту history для навигации.

В вашем компоненте, который запускает создателя действия:

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

Тогда внизу кода, куда вы звоните, подключитесь:

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...