如何封装React组件中的方法以消除重复的loading和error状态管理代码
解决方案
你可以用原生JavaScript的高阶函数特性实现逻辑封装,不需要任何第三方依赖或实验性语法,改造成本极低。
基础实现
首先定义一个通用的异步逻辑包装函数:
const withLoadingAndError = function(handler) { // 此处用普通函数而非箭头函数,保证this指向调用它的组件实例 return async (...args) => { try { this.setState({ loading: true }); // 透传参数和this上下文到业务逻辑 const result = await handler.apply(this, args); this.setState({ loading: false }); // 透传业务逻辑的返回值,不影响原有逻辑的返回使用 return result; } catch (err) { // 同时修复你原有代码的问题:出错时也重置loading状态 this.setState({ loading: false, error: err }); // 如果需要业务层单独处理错误,可取消下面的注释把错误抛出 // throw err; } }; };
使用方式
你原来的业务函数只要保留核心逻辑,套一层上面的包装函数即可:
doSomething = withLoadingAndError(async (params) => { // 此处仅写业务逻辑,不需要手动处理loading和error状态 const result = await Backend.post('/xxx', params); // 其他业务处理逻辑 return result; })
进阶自定义版本
如果不同请求需要用不同的loading、error状态字段(比如避免多个请求共用一个loading导致冲突),可以给包装函数加配置参数:
const withLoadingAndError = function(handler, options = {}) { const { loadingKey = 'loading', errorKey = 'error' } = options; return async (...args) => { try { this.setState({ [loadingKey]: true }); const result = await handler.apply(this, args); this.setState({ [loadingKey]: false }); return result; } catch (err) { this.setState({ [loadingKey]: false, [errorKey]: err }); } }; };
自定义字段使用示例
// 提交表单用单独的loading、error状态 submitForm = withLoadingAndError(async (formData) => { return Backend.post('/submit', formData); }, { loadingKey: 'submitLoading', errorKey: 'submitError' }) // 获取列表用单独的loading、error状态 fetchList = withLoadingAndError(async (page) => { return Backend.get('/list', { params: { page } }); }, { loadingKey: 'listLoading', errorKey: 'listError' })
注意事项
- 如果你的业务逻辑内部已经写了try catch,需要把捕获到的错误重新抛出,才能被外层的包装函数捕获到并设置error状态
- 如果需要在单个业务函数中做特殊的错误处理,可以打开包装函数里的
throw err注释,在业务层单独catch处理即可 - 包装函数完全复用了你原来的逻辑顺序,行为和你原有手写的代码完全一致,不需要担心副作用问题
内容的提问来源于stack exchange,提问作者user7111260
相关产品推荐
相关产品推荐

