我正在关注本教程:https://github.com/callicoder/spring-security-react-ant-design-polls-app
我已经有一个可以生成JWT的工作后端,并且API还使用GET
方法在http://localhost:8080/api/user/me中返回了当前用户的详细信息。背面一切都很好(已通过Postman测试)。
但是,当我尝试将当前用户从API加载到App
组件的状态时,我遇到了问题。这个想法是创建到Login
组件的路由,并将其传递给对handleLogin
方法的引用,该方法执行getCurrentUser()
并重定向到主页。
所有这些操作都是通过导入名为APIUtils
的文件来完成的,该文件具有与API交互的方法。特别是,它具有通用的request()
方法,该方法使用获取返回承诺,并接收请求的参数。问题是我无法得到APIUtils/request()
方法返回的诺言的响应。它说它是未定义的。
App.js
//imports
class App extends Component {
state = {
currentUser: null
}
loadCurrentUser = () => {
// getCurrentUser is imported from APIUtils/index.js
getCurrentUser()
.then(response => {
this.setState({
currentUser: response
});
})
.catch(error => {
console.log(error)
});
}
handleLogin = () => {
this.loadCurrentUser();
this.props.history.push("/");
}
componentDidMount() {
this.loadCurrentUser();
}
render () {
return (
<Switch>
<Route exact path='/' component={Landing} />
<Route path="/login"
render={
(props) => <Login onLogin={this.handleLogin} {...props} />
}/>
</Route>
</Switch>
);
}
}
export default withRouter(App);
APIUtils / index.js
const request = (options) => {
const headers = new Headers({
'Content-Type': 'application/json',
})
if(localStorage.getItem(ACCESS_TOKEN)) {
headers.append('Authorization', 'Bearer ' + localStorage.getItem(ACCESS_TOKEN))
}
const defaults = { headers: headers };
options = Object.assign({}, defaults, options);
return fetch(options.url, options)
.then(response => {
response.json().then(json => {
if(!response.ok) {
return Promise.reject(json);
}
return json;
})}
);
}
// expects loginRequest = { email: 'something', password: 'something' }
export const login = (loginRequest) => {
return request({
url: API_BASE_URL + "/auth/signin",
method: 'POST',
body: JSON.stringify(loginRequest)
});
}
export const getCurrentUser = () => {
if(!localStorage.getItem(ACCESS_TOKEN)) {
return Promise.reject("No access token set.");
}
return request({
url: API_BASE_URL + "/user/me",
method: 'GET'
});
}
Login.js
class Login extends Component {
state = {
email: '',
password: ''
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
const loginRequest = Object.assign({}, this.state);
login(loginRequest)
.then(response => {
localStorage.setItem(ACCESS_TOKEN, response.accessToken);
this.props.onLogin();
}).catch(error => {
if(error.status === 401) {
console.log('Your Username or Password is incorrect. Please try again!');
} else {
console.log('Sorry! Something went wrong. Please try again!');
}
});
}
render () {
return (
<React.Fragment>
/*
* form using onSubmit={this.handleSubmit}
* inputs using value={this.state.email} and onChange={this.handleChange}
* button of type="submit"
*/
</React.Fragment>
);
}
}
export default Login;
有了这个,我登录并加载控制台后,通过控制台检查了登录并将本地令牌存储在本地存储中,APIUtils中的request()方法也返回了URL响应:http://localhost:8080/api/user/me ,并返回代码中的json
承诺,如下所示:
{
"id": 23,
"name": "john",
"email": "new@mail.com"
}
但是当我尝试使用then()访问App.js中getCurrentUser()的响应时,它的响应是不确定的,因此我无法将其设置为状态。
答案 0 :(得分:1)
您没有返回fetch()
的结果:
return fetch(options.url, options)
.then(response => { // you forgot that this is also a function
return response.json().then(json => { // <--- missing return!!
if(!response.ok) {
return Promise.reject(json);
}
return json;
})}
);
我可以理解为什么您可能会错过它。很容易错过。这就是为什么您应该使用Promises的主要功能-发明它们的原因-Promise链的原因:
let ok = null;
return fetch(options.url, options)
.then(response => {
ok = response.ok;
return response.json();
})
.then(json => {
if (!ok) {
return Promise.reject(json);
}
return json;
});
通过这种方式更容易发现缺失的回报,因为您可以轻松地检查每个then
块是否具有return
陈述。