代码之家  ›  专栏  ›  技术社区  ›  Arian

在react redux应用程序中处理请求呼叫响应,以避免使用回调

  •  0
  • Arian  · 技术社区  · 8 年前

    这是一个设计问题,但我想知道是否有处理此类情况的最佳实践。

    我有一个react redux应用程序。应用程序状态结构如下所示:

    {
       groups: {gid1: group1, gid2: group2, ....},
       expenses: {eid1: expense1, eid2: expense2, ...}, 
       //.... the rest
    }
    

    这个 NewGroup 组件旨在创建新组。如果创建请求(对后端的ajax请求)成功,则会将其添加到处于应用状态的组列表中。这个 新建组 ,这是一个模式,已关闭,组列表将更新。

    尽管 新建组 如果请求未成功,则不应关闭组件。

    主要的问题是:我是否应该将请求状态(如果成功或不成功,在后一种情况下的错误消息,如果结果返回或未返回,等等)合并到应用程序状态?这就是我真正怀疑的地方,因为它使应用程序状态非常丑陋、庞大,在某些情况下,它无法处理某些情况,在这种情况下:创建一个新组。

    假设我将响应状态代码和错误消息添加到应用程序状态:

    {
       groups: {
          newGroupId1: {
              data: newGroupData1,// null in case it was not successful
              isLoading: true/false, // if the call is returned or not
              errorFetching: message1
          }
       }
    }
    

    在对后端的第二个不成功的create请求中,无法区分以前的调用和当前的调用,因为它们都有 errorFetching 和类似的 isLoading 价值观(例如,两者都有“未找到组” 错误获取 “false”表示 正在卸载 )

    在以下情况下,区分请求调用的状态和应用程序状态中的真实数据的最佳做法是什么 redux 是否正在使用?

    更新1

    这是减速器:

    import { FETCH_GROUPS_SUCCESS, FETCH_GROUPS_ERROR, CREATE_GROUP_SUCCESS, CREATE_GROUP_ERROR, DELETE_GROUP, FETCH_GROUP_SUCCESS, FETCH_GROUP_ERROR } from '../actions/creators';
    
    export const FULL_GROUP = 'full_group';
    export const SNIPPET_GROUP = 'snippet_group';
    
    const INITIAL_STATE = {
      data: null,
      isLoading: true,
      errorFetching: null
    };
    
    export default function(state=INITIAL_STATE, action) {
      switch(action.type) {
        case FETCH_GROUPS_SUCCESS:
          return {
            data: _.zipObject(_.map(action.payload, group => group.id),
              _.map(action.payload, group => ({
                  data: group,
                  isLoading: true,
                  errorFetching: null,
                  mode: SNIPPET_GROUP
              }))
            ),
            isLoading: false,
            errorFetching: null
          };
        case FETCH_GROUPS_ERROR:
          return {
            data: null,
            isLoading: false,
            errorFetching: action.payload.error
          };
        case FETCH_GROUP_SUCCESS:
          return {
            data: {...state.data, [action.payload.id]: {
              data: action.payload,
              isLoading: false,
              errorFetching: null,
              mode: FULL_GROUP
            }},
            isLoading: false,
            errorFetching: null
          };
        case FETCH_GROUP_ERROR:
          const stateWithoutId = _.omit(state, action.payload.id);
          return {
            data: {...stateWithoutId},
            isLoading: false,
            errorFetching: null
          };
        case CREATE_GROUP_SUCCESS:
          debugger;
          //TODO: how to let the NewGroup know that a group was created successfuly ?
          return { ...state, [action.payload.id]: {
            data: action.payload,
            isLoading: true,
            errorFetching: null,
            mode: SNIPPET_GROUP
          }};
        default:
          return state;
      }
    }
    

    这是操作创建者:

    export function groupsFetchSucceeded(response) {
      return {
         type: FETCH_GROUPS_SUCCESS,
         payload: response
      }
    }
    
    export function groupsFetchErrored(errorWithId) {
      return {
         type: FETCH_GROUPS_ERROR,
         payload: errorWithId
      }
    }
    
    export function groupCreateSucceeded(group) {
      return {
        type: CREATE_GROUP_SUCCESS,
        payload: group
      }
    }
    
    export function groupCreateErrored(errorWithId) {
      return {
        type: CREATE_GROUP_ERROR,
        payload: response
      }
    }
    
    export function groupFetchSucceeded(groupData) {
      return {
         type: FETCH_GROUP_SUCCESS,
         payload: groupData
      }
    }
    
    export function groupFetchErrored(errorWithId) {
      //handle the error here
      return {
         type: FETCH_GROUP_ERROR,
         payload: errorWithId
      }
    }
    

    这是组件。拜托!不管这是一个redux表单,我不管它是不是redux表单,我只是在寻找一个大致的想法。你可以假设它是 react-redux 具有的组件 mapStateToProps mapDispatchToProps 和其他相关的东西。

    import { createGroup } from '../../actions';
    import { validateName, validateDescription } from '../../helpers/group_utils';
    import { renderField, validate } from '../../helpers/form_utils';
    
    const validators = {
      name: validateName,
      description: validateDescription
    };
    
    class NewGroup extends Component {
    
      _onSubmit(values) {
        this.props.createGroup(values);
      }
    
      render() {
        const { handleSubmit } = this.props;
        return (
          <div>
            <form onSubmit={handleSubmit(this._onSubmit.bind(this))}>
              <Field name="name" label="Name" type="text" fieldType="input" component={renderField.bind(this)}/>
              <Field name="description" label="Description" type="text" fieldType="input" component={renderField.bind(this)}/>
              <button type="submit" className="btn btn-primary">Create</button>
              <button type="button" className="btn btn-primary" onClick={() => this.props.history.push('/group')}>Cancel</button>
            </form>
          </div>
        );
      }
    }
    
    export default reduxForm({
      validate,
      //a unique id for this form
      form:'NewGroup',
      validators
    })(
      connect(null, { createGroup })(NewGroup)
    );
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   blaz    8 年前

    问题的棘手之处在于,虽然您希望在redux状态下记录所有请求状态,但请求的数量可能会成倍增加,如果处理不好,会占用大量状态的容量。另一方面,我不认为区分请求数据和状态数据有什么大不了的:您只需要在状态中将它们分开:

    {
        groups: {gid1: group1, gid2: group2, ....},
        groupRequests: {grid1: request1, grid2: request2, ...},
        expenses: {eid1: expense1, eid2: expense2, ...},
        ...
    }
    

    其中每组数据包含:

    {
        data: groupData,
        lastRequestId: grid // optional
    }
    

    每个组请求数据包含:

    {
        groupId: gid,
        isLoading: true/false,
        errorFetching: message
    }
    

    发送新请求时,您可以在 groupRequests 并在那里跟踪它; NewGroup 组件只需要持有groupId就可以找到最近激发的请求并查看其状态。当您需要了解以前请求的状态时,请从列表中获取它们。

    同样,这种方法的问题是 组请求 是一次性使用,意思是在某一点(例如,当 新建组 组件关闭),您甚至不再需要它。因此,请确保在 groupRequest 长得太大了。

    我的建议是,在处理redux状态时,尽量将其正常化。如果需要1-n关系(分组数据和创建组的请求数据),请将其进一步分解,而不是将它们分组在一起。并尽可能避免存储一次性使用的数据。