React Redux 路由只是刷新

React Redux routing just refreshes

我必须在登录后将用户重定向到应用程序的主要组件。我正在使用 redux 来管理状态。

我试图从 this 线程

更改我的登录方法
import axios from 'axios'
import { push } from 'react-router-redux'
import { API_URL } from '../utils/apiUrl'

export const loginUser = creds => {
  return dispatch => {
    dispatch(loginRequest(creds))

    axios({
      method: "post",
      url: API_URL + "/auth_token",
      data: { auth: creds }
    }).then(res => {

       dispatch(push('/home')) /* dispatch an action that changes the browser history */ 

      })

    }).catch(err =>
      dispatch(loginFailure('Wrong email/password combination'))
    )
  }
}

所以在我的例子中它看起来像这样:

export function authenticate(user, password) {
        var data = {
            "username" : user,
            "password": password
        };
        return function(dispatch) {
            return axios({
                url: 'someserver:xxxx/login',
                timeout: 20000,
                method: 'POST',
                data: data,               
            }).then(function(response) {
                dispatch(loggedIn(response.data.token));
            }).then(res => {
                dispatch(push('/main'));    <------ route to main page
            }).catch(function(error) {
                if (error.response) {
                    // DEBUGGING
                    console.log(error.response.data);
                    console.log(error.response.status);
                    console.log(error.response.headers);
                }
            })
        }
    }
    const loggedIn = (token) => ({
        type: "LOGIN",
        token
    })

App.js 看起来像这样:

render() {
    return (     
      <Router>
        <div style={{textAlign : 'center'}}>
        <Route path="/main" component={Main}/>
          <img src={Logo} alt="fireSpot"/>
          <p style={{paddingTop: '2%'}}>LOGIN</p>
          <form>
              <TextField
                id="username"
                label="USERNAME"
                value={this.state.username}
                onChange={(event) => this.handleUsername(event)}
                margin="normal"
              /> <br />
              <TextField
                value={this.state.password}
                onChange={(event) => this.handlePassword(event)}
                id="password"
                label="PASSWORD"
                type="password"
                autoComplete="current-password"
                margin="normal"
              />
              <br />

              <MuiThemeProvider theme={theme}>
                <Button
                  onClick={
                    this.handleSubmit
                  }                    
                  disabled={!this.validateForm()}
                  type="submit"
                  variant="raised"
                  color="secondary"
                >
                Anmelden
              </Button>

            </MuiThemeProvider>
          </form>
        </div>
      </Router>
    );
  }
}

handleSubmit方法:

handleSubmit = (event) => {
    event.preventDefault();
    this.props.login();
}

mapDispatchToProps:

const mapDispatchToProps = (dispatch) => {
  return { 
    login : function() {
      dispatch(authenticate(this.state.username, this.state.password));
    }
  }
}

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

登录有效。我什至可以打印得到的响应:{type: "@@router/CALL_HISTORY_METHOD", payload: {…}},但什么也没有发生。

有什么想法吗?

编辑:

同时我添加到 App.js

handleSubmit = async (event) => {
    event.preventDefault();

    await this.props.login();
    this.props.history.push('/main')


}

并用 withRouter:

将 App.js 中的所有导出内容包装起来
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));

我将 ReactDOM.render(<App store={store}/>... 行更改为

ReactDOM.render(<Router><div><App store={store} /> </div></Router>, document.getElementById('root'));

消除了 A <Router> may have only one child element 错误。现在它似乎重定向到某个地方,但它只是结束于:

Could not find "store" in either the context or props of "Connect(Main)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(Main)".

编辑 2:

我导入了 Provider 并将 store 作为 props 传递给它,现在它可以工作了。

ReactDOM.render(
<Provider store={store}>
    <Router>
        <div>
            <App store={store} /> 
        </div>
    </Router>
</Provider>, document.getElementById('root'));

现在唯一的问题是,它只是在登录字段上添加了 Main 的内容。有什么想法吗?

编辑 3: 我从 App.js 中删除了与 Router 相关的所有内容,并像这样编辑了 index.js 文件。

<Provider store={store}>
    <Router>
        <div>
            <Route exact path="/" component={App}/>
            <Route path="/main" component={Main}/> 
        </div>
    </Router>
</Provider>, document.getElementById('root'));

它解决了登录后的堆叠组件问题。我不知道如何从 login return 一些东西,这样应用程序就不会前进到 Main 如果正如@ivica.moke 在他的评论中所写,凭据是错误的。

使登录异步,并等待登录的响应,然后在该过程完成后推送到“/main”。您甚至可以 return 从 login() 操作和基于响应的内容甚至推送到主(如果成功)或强制输入有效凭据(如果未成功登录)。

handleSubmit =async (event) => {
    event.preventDefault();
    await this.props.login();
    this.props.history.push('/main');
}

编辑 在您使用 axios 的 API 调用中,您的服务器有望 return 一些状态代码。在 axios 收到 res.then 中,您可以检查该状态代码(使用 console.log(res) 检查)以查看您的 API return秒。然后就从 .then return resres.status.

axios.post(url,data)
   .then(res => {
  // here you check status code from API response
  // and return response or it's status code
  return res;
})
   .catch(error => {
  //if error meaning not statusCode 200 (login failed for some reason)
  return error;
});

内部 handleSubmit

handleSubmit =async (event) => {
        event.preventDefault();
        const res = await this.props.login();
        // this res is what you get from action
        // for example
        if(res.status === 200){
        // 200(status ok) meaning successful login
        this.props.history.push('/main');
        }
        else {
        // login failed
        }
}

我希望这能让它更清楚一些。