对于我的React组件,我使用Redux(react-redux)和Redux Thunk来维护应用程序状态 .
有一个 ShowGroup
组件从后端检索 group
. 如果该组不存在(或在任何其他错误情况下),则调用错误回调以更新状态 .
class ShowGroup extends Component {
constructor(props) {
super(props);
this.groupId = this.props.match.params.id;
this.state = {
'loaded': false,
'error': null
};
}
_fetchGroupErrorCallback = response => {
this.setState({loaded: true, error: response});
}
componentDidMount() {
this.props.fetchGroup(this.groupId, this._fetchGroupErrorCallback);
}
render() {
//what is the best practice here ?
let group = this.props.groups[this.groupId];
if (!group) {
if (!this.state.loaded) {
return <div>Loading group ....</div>;
}
if (this.state.error) {
return <div>{this.state.error.data.message}</div>;
}
}
return (
<div className="show-group">
<form>
{_.map(FIELDS, renderField.bind(this))}
</form>
</div>
);
}
}
function mapStateToProps(state) {
return { groups: state.groups };
}
const mapDispatchToProps = (dispatch) => {
return {
fetchGroup: (id, callback) => dispatch(fetchGroup(id, callback)),
updateGroup: (id) => dispatch(updateGroup(id))
};
};
export default reduxForm({
validate,
//a unique id for this form
form:'ShowGroup',
fields: _.keys(FIELDS),
fields_def: FIELDS
})(
connect(mapStateToProps, mapDispatchToProps)(ShowGroup)
);
(这是一个无关紧要的 redux-form
组件)
export function fetchGroup(id, fetchErrorCallback) {
return (dispatch) => {
axios.get(URL, AUTHORIZATION_HEADER)
.then(response => {
dispatch(groupFetched(response))
})
.catch(({response}) => {
fetchErrorCallback(response);
dispatch(groupFetchErrored(response));
})
};
}
groupFetchedErrored
动作创作者:
export function groupFetchErrored(response) {
//handle the error here
return {
type: FETCH_GROUP_ERROR,
response
}
}
还原剂:
export default function(state=INITIAL_STATE, action) {
switch(action.type) {
//....
case FETCH_GROUP_ERROR:
return _.omit(state, action.response.data.id);
default:
return state;
}
}
The problem:
A. 如果出现错误响应,组件将被渲染三次:1 . 首次加载(在进行ajax调用之后)2 . 调用 _fetchGroupErrorCallback
并设置状态,这将导致渲染3. groupFetchErrored
是调度导致另一个渲染
B. 如果响应成功,组件会被渲染两次,但状态不正确,因为没有更新它(并且我没有't think it'正确为它添加回调)
在React中使用Redux和Redux-Thunk时,处理ajax错误响应的最佳实践是什么?动作创建者和减速器应该如何通知组件有什么问题?
Update 1
这是我的根减速器:
const rootReducer = combineReducers({
form: formReducer,
groups: groupReducer
});
export default rootReducer;
如你所见,我有 groups
这是一个形式的对象:
{
groupId1: groupData1,
groupId2, groupData2,
....
}
所以,另一个问题是,我应该如何指定一个组正在加载(我在 groups
级别上没有 isLoading
或 errorFetching
,并且它没有't seem to be a good idea to add one entry for each invalid group id user may try. Or maybe there'方式将无效的组ID放入 Map 然后清理它?我不知道但是,我知道应该在哪里发生 .
1 回答
将与获取相关的所有状态数据放入Redux存储中 . 然后商店成为你的唯一真相来源 .
然后,您可以完全省略
fetchErrorCallback
.您已经在减速器中有一个地方通知错误:
您可以将错误存储在redux状态:
然后通过
mapStateToProps
将errorFetching
和isLoading
传递给您的组件,就像您已经使用groups
一样 .同样要正确跟踪
isLoading
,最好在开始提取时(在调用axios.get
之前)调度另一个动作,也许FETCH_GROUP_STARTED
. 然后在您的reducer中,当调度该动作类型时,将isLoading
设置为true
.如果这是我的代码,我会做出另一个更改:我不会将
response
传递给动作创建者,而是删除相关数据并将其传递给他们 . 因此reducer不需要知道如何处理response
对象;它只是接收正确显示组件所需的数据 . 这样,处理axios调用并且必须知道它们返回的对象的形状的所有代码都在一个地方 - 动作函数 . 就像是:动作创作者
行动
减速机
你可能已经注意到我在上面的动作创建者中使用了
action.payload
.它需要与动作创建者紧密耦合;它知道数据总是在
payload
字段中 . (也许这就是你用response
做的事情,但看起来它似乎专门用于http响应 . )