如何setState()从AJAX请求收到的响应,以便我可以在页面中显示它们?
constructor(props)
{
super(props);
this.state = {
email: '',
first_name: '',
middle_name: '',
country: '',
country_code: '',
mobile_number: '',
gender: ''
}
}
componentDidMount()
{
store.dispatch(getUserProfile())
.then(() => {
const user = this.props.userProfile.userProfile && this.props.userProfile.userProfile.data.data;
this.setState({
email: user.email,
first_name: user.first_name
});
})
}
render()
{
return (
<div className="form-group col-sm-12">
<label htmlFor="email">Email*</label>
<input type="email" name="email" value={this.state.email || ''}/>
</div>
<div className="form-group col-sm-12">
<label htmlFor="email">First Name*</label>
<input type="email" name="email" value={this.state.first_name || ''}/>
</div>
)
}
显然,我不能将.then()与store.dispatch方法一起使用。
未捕获的TypeError:_store2.default.dispatch(...)。则不是函数
getUserProfile() action function
import axios from 'axios';
export function getUserProfile()
{
return function(dispatch)
{
dispatch(userProfileSuccess(false));
dispatch(userProfileError(null));
const request = axios
({
url: "http://testapi/auth/v1/user/details",
method: "get",
headers: {
'Content-Type': 'application/json',
'Authorization' : 'Bearer ' + localStorage.getItem('access_token')
}
})
.then(function(response) { dispatch(userProfileSuccess(response)); })
.catch(function(error) {
console.log(error)
});
return {
type: 'USER_PROFILE_SUCCESS',
payload: request
}
};
}
function userProfileSuccess(userProfile)
{
return {
type: 'USER_PROFILE_SUCCESS',
userProfile: userProfile
};
}
function userProfileError(userProfileError)
{
return {
type: 'USER_PROFILE_ERROR',
userProfileError: userProfileError
};
}
export default getUserProfile;
在AJAX调用中,我试过:
.then(function(response) {
return new Promise((resolve) => {
dispatch(userProfileSuccess(response));
resolve();
});
})
但是控制台报告了同样的错误。
我可以传递给store.dispatch
的回调吗?对此有什么正确的解决方法?
答案 0 :(得分:2)
您可以在componentDidMount()
中添加回调componentDidMount()
{
store.dispatch(getUserProfile(), () => {
const user = this.props.userProfile.userProfile && this.props.userProfile.userProfile.data.data;
this.setState({
email: user.email,
first_name: user.first_name
});
})
}
这可能不完全相同,我只是想让你知道如何使用箭头功能添加回调,这样你就不需要使用了。
答案 1 :(得分:1)
Redux将状态存储在Redux存储中,与React组件状态(想想setState)分开。你快到了。您需要做的是将结果数据从异步调度引导到redux存储,然后引导到本地组件状态。下面的步骤3和4。
答案 2 :(得分:1)
当您使用redux时,您的redux存储应该跟踪api调用何时正在进行或已完成或遇到一些错误。因此,不应该传递任何回调或承诺,而是应该为每个事件分派一个动作,如处理,成功,错误等(你已经在getprofile函数中做了)。虽然我会说你很好地区分过程,成功,错误。例如,你的getprofile方法应该大致看起来像这样
export function getUserProfile()
{
return function(dispatch)
{
dispatch(userProfileProcessing());
const request = axios
({
url: "http://testapi/auth/v1/user/details",
method: "get",
headers: {
'Content-Type': 'application/json',
'Authorization' : 'Bearer ' + localStorage.getItem('access_token')
}
})
.then(function(response) { dispatch(userProfileSuccess(response)); })
.catch(function(error) {
dispatch(userProfileError(response))
console.log(error)
});
};
}
这正是我喜欢的。如果你想要你的方式,那也没关系。
现在每次调度任何动作时,redux都会更新reducer状态。这就是你可以设置/重置一些标志的地方,让组件知道api调用发生了什么。所以你的减速器可能看起来像这样:
//getUserProfileReducer.js
userProfileReducer = (state = {}, action) => {
switch (action.type) {
case 'USER_PROFILE_PROCESSING':
return({
...state,
processing: true,
success: false,
fail: false,
userProfile: null,
})
case 'USER_PROFILE_SUCCESS':
return({
...state,
processing: false,
success: true,
fail: false,
userProfile: action.userProfile,
})
case 'USER_PROFILE_Error':
return({
...state,
processing: false,
success: false,
fail: true,
userProfile: null,
})
}
现在您需要做的就是从您的组件访问此状态,以便您可以根据该状态采取必要的操作。为此,您可以使用mapStateToProps函数将redux状态转换为组件的prop。
constructor(props)
{
super(props);
this.state = {
email: '',
first_name: '',
middle_name: '',
country: '',
country_code: '',
mobile_number: '',
gender: ''
}
}
componentWillReceiveProps(newProps){
if(newProps.userProfileStatus.success){
// The success flag is true so set the state
const user = newProps.userProfileStatus;
this.setState({
email: user.email,
first_name: user.first_name
});
}
else if(newProps.userProfileStatus.processing){
// Api call is in progress so do action according to that like show loader etc.
}
}
componentDidMount()
{
store.dispatch(getUserProfile())
}
render()
{
return (
...
)
}
const mapStateToProps = state => {
return {
userProfileStatus: state.userProfileReducer,
}
}