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 res
或 res.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
}
}
我希望这能让它更清楚一些。
我必须在登录后将用户重定向到应用程序的主要组件。我正在使用 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
:
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 res
或 res.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
}
}
我希望这能让它更清楚一些。