React Redux路由只是刷新

时间:2018-03-28 11:16:40

标签: reactjs react-redux react-router-v4 react-router-dom

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

我尝试从this thread:

更改我的登录方法
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:

我导入了提供商并将store作为props传递给它,现在它可以正常工作。

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

现在只发布,它只是在登录字段中添加Main的内容。有什么想法吗?

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

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

它在登录后解决了堆叠组件问题。我不知道如何从login返回一些内容,以便在凭据确认时应用程序不会前进到Main错误,正如@ ivica.moke在评论中写道的那样。

1 个答案:

答案 0 :(得分:1)

登录异步,并等待登录响应,然后在该过程完成后推送到&#39; / main&#39;。您甚至可以从login()操作返回一些内容,并根据响应甚至推送到main(如果成功)或强制输入有效凭据(如果未成功登录)。

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

修改 在使用axios的API调用中,您的服务器有望返回一些状态代码。来自.then的{​​{1}}内部,您可以在其中收到axios,您可以检查该状态代码(请参阅console.log(res))以查看您的API返回的内容。然后只从res返回.thenres

res.status

在handleSubmit内部

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

我希望这会让它更清晰。