实现的管理系统有一个功能是A登录系统和B登录系统用的同一个账号时,A的登录状态就会被B挤掉,表现为A在点击导航栏,后台返回401状态码,但是无数据响应。并跳转回登录页面。
这个时候会出现个问题,就是重新登录,再点击相同页面就会发生数据渲染或者数据绑定错误,发现原因是,退出系统modal中的state值并不会清空或者恢复默认值,而是保留上一次的值,所以当后台返回401无响应值得时候,会有错误的赋值,而页面渲染的顺序是@connect进行数据绑定(这时绑定错误数据,页面报错)->componentWillMount->render->componnetDidMount。所以就会先绑定错误数据在加载正确数据。
现在有两个解决办法
①当后台无数据返回,前台做判断不进行赋值。在modals的effect中修改,对response的返回值进行验证。所使用的函数是自己封装的checkAPIStatus函数
//checkAPIStatus函数
export function checkAPIStatus(data) {
if(data && !(data instanceof Error) && typeof data == 'object' && data.success && data.obj) return true;
return false;
}
//modals
effects: {
*fetchUploadList({ payload, callback },{ call, put}){
yield put({
type: 'changeUploadListLoading',
payload: true,
});
const response = yield call(queryUploadList, payload);
if(checkAPIStatus(response)){
yield put({
type: 'saveUploadList',
payload: response,
})
}
yield put({
type: 'changeUploadListLoading',
payload: false,
})
},
}
②当因为无权限,后台返回401状态码,跳转到重新登录页面的时候,自动模拟页面的刷新,重置modals中state的初值
return fetch(url, newOptions)
.then(checkStatus)
.then((response) => {
if (newOptions.method === 'DELETE' || response.status === 204) {
return response.text();
}
return response.json();
})
.catch((e) => {
const { dispatch } = store;
const status = e.name;
if (status === 401) {
dispatch(routerRedux.push('/user/login'));
window.location.reload();
return;
}
});
③参考了评论中的方法,就是在componentWillUnmount的时候dispatch一个reducer来重置数据,这个方法也可谓是简单有效。此解决方法的麻烦的地方是要在所有的页面卸载的时候手动重置数据,代价也比较的大。
//在页面卸载之前dispatch一个重置数据的reducer
componentWillUnmount(){
const { dispatch } = this.props;
dispatch({
type: 'administrativeUpload/resetUploadList',
});
}
//modal中重置数据,将数据设置为初始值,这样重新登录之后再点击该页面将会恢复初始状态
resetUploadList(state, { payload }) {
return {
...state,
uploadList: {
success:"false",
msg:"error",
obj:{
rows: [],
total: null,
pageSize: null,
pageNumber: null,
},
},
};
},