Spinner在Redux中加载

时间:2016-03-04 01:20:36

标签: redux redux-thunk react-redux

在Redux中进行某种旋转指示器的理想方法是什么?

假设我有一个名为Things的REST API。在React组件中,我有Thing CardThing Card ListAdd Thing Form

如果我每次都想旋转微调器,那么理想的方法是什么: *)来自服务器的GET Things *)PUT Thing/123到服务器 *)来自服务器的DELETe Thing/123 *)POST Thing到服务器

我知道这个想法几乎在Redux Store中设置了一个名为isPending: true的状态。

这就是我所拥有的

store = {
  things: {
     data: [], // array of things
     isPending: true,
     isSuccess: false,
     isError: false,
     error: undefined
  }
};

但是,这个isPending: true是针对什么行动的?得到?放?删除? POST?如果我将所有这些操作都依赖于同一个属性isPending: true,那么奇怪的事情就会开始发生,例如=>当我执行POST Things时,isPending暂时为真,而依赖于该属性的其他组件也会显示它们的微调器。

这是我的代码

import _ from 'lodash';
import Api from '../../utils/api';

export const thingApi = new Api({ 
  url: '/api/things',
  token: localStorage.getItem('token')
});

// ------------------------------------
// Constants
// ------------------------------------
export const GET_THING_PENDING = 'GET_THING_PENDING';
export const GET_THING_SUCCESS = 'GET_THING_SUCCESS';
export const GET_THING_FAILURE = 'GET_THING_FAILURE';
export const POST_THING_PENDING = 'POST_THING_PENDING';
export const POST_THING_SUCCESS = 'POST_THING_SUCCESS';
export const POST_THING_FAILURE = 'POST_THING_FAILURE';
export const DELETE_THING_PENDING = 'DELETE_THING_PENDING';
export const DELETE_THING_SUCCESS = 'DELETE_THING_SUCCESS';
export const DELETE_THING_FAILURE = 'DELETE_THING_FAILURE';

// ------------------------------------
// Actions
// ------------------------------------
export const getThing = () => {
  return (dispatch, getState) => {
    dispatch(getThingPending());
    return thingApi.get()
      .then(({ data }) => {
        dispatch(getThingSuccess(data));
      })
      .catch(({ error }) => {
        dispatch(getThingFailure(error));
      });
  };
};

export const postThing = ({ name }) => {
  return (dispatch, getState) => {
    dispatch(postThingPending());
    const body = { name };
    return thingApi.post({ data: body })
      .then(({ data }) => {
        dispatch(postThingSuccess(data));
      })
      .catch(({ error }) => {
        dispatch(postThingFailure(error));
      });
  };
};

export const deleteThing = (_id) => {
  return (dispatch, getState) => {
    dispatch(deleteThingPending());
    return thingApi.delete({ 
      url: `/api/things/${_id}`
    }).then((res) => {
        dispatch(deleteThingSuccess(_id));
      })
      .catch(({ error }) => {
        dispatch(deleteThingPending(error));
      });
  };
};

export const getThingPending = () => ({
  type: GET_THING_PENDING
});

export const getThingSuccess = (things) => ({
  type: GET_THING_SUCCESS,
  payload: things
});

export const getThingFailure = (error) => ({
  type: GET_THING_FAILURE,
  payload: error
});

export const postThingPending = () => ({
  type: POST_THING_PENDING
});

export const postThingSuccess = (thing) => ({
  type: POST_THING_SUCCESS,
  payload: thing
});

export const postThingFailure = (error) => ({
  type: POST_THING_FAILURE,
  payload: error
});

export const deleteThingPending = () => ({
  type: DELETE_THING_PENDING 
});

export const deleteThingSuccess = (_id) => ({
  type: DELETE_THING_SUCCESS,
  payload: _id
});

export const deleteThingFailure = (error) => ({
  type: DELETE_THING_FAILURE,
  payload: error
});

export const actions = {
  getThing,
  getThingSuccess,
  postThing,
  postThingSuccess,
  deleteThing,
  deleteThingSuccess
};

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [GET_THING_PENDING] (state, action) {
    return { 
      isPending: true,
      isSuccess: false,
      isFailure: false
    };
  },

  [GET_THING_SUCCESS] (state, { payload: data }) {
    return {
      isPending: false,
      isSuccess: true,
      data,
      isFailure: false
    };
  },

  [GET_THING_FAILURE] (state, { payload: error }) {
    return { 
      isPending: false,
      isSuccess: false,
      isFailure: true,
      error
    };
  },

  [POST_THING_PENDING] (state, action) {
    return {
      isPending: true,
      isSuccess: false,
      isError: false
    };
  },

  [POST_THING_SUCCESS] (state, { payload: data }) {
    debugger;
    return {
      isPending: false,
      isSuccess: true,
      data: [ ...state.data, data ],
      isError: false
    };
  },

  [POST_THING_FAILURE] (state, { payload: error }) {
    return {
      isPending: false,
      isSuccess: false,
      isFailure: true,
      error
    };
  },

  [DELETE_THING_PENDING] (state, action) {
    return {
      ...state,
      isPending: true,
      isSuccess: false,
      isFailure: false
    };
  },

  [DELETE_THING_SUCCESS] ({ data }, { payload: _id }) {
    const index = _.findIndex(data, (d) => d._id === _id);

    const newData = [
      ...data.slice(0, index),
      ...data.slice(index + 1)
    ];

    return {
      isPending: false,
      isSuccess: true,
      data: newData,
      isFailure: false
    };
  },

  [DELETE_THING_FAILURE] (state, { payload: error }) {
    return {
      isPending: false,
      isSuccess: false,
      isFailure: true,
      error
    };
  }

};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  isPending: false,
  isSuccess: false,
  data: [],
  isFailure: false,
  error: undefined
};

export default function thingReducer (state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type];

  return handler ? handler(state, action) : state;
}

那么,如果我需要为每个动作表示微调器(或错误),我该怎么办?

我应该做点什么

store = {
  things: {
    get: {
      data: [],
      isPending,
      isError,
      isSuccess,
      error
    },
    post: {
      data: [],
      isPending,
      isError,
      isSuccess,
      error
    },
    put: {
      data: [],
      isPending,
      isError,
      isSuccess,
      error
    },
    delete: {
      data: [],
      isPending,
      isError,
      isSuccess,
      error
    }
  }
};

看起来错误的做法

1 个答案:

答案 0 :(得分:2)

如果您只想知道 if 请求处于待处理状态并且使用什么方法(get / post / put / delete),您可以只存储该方法在你所在州与其他人一起打字,例如:

{
  data: [],
  isPending: true,
  method: 'POST',
  isSuccess: false,
  isError: false,
  error: undefined
}

然后您可以在组件中检查它,例如:

const { isPending, method } = this.state;

if (isPending && method === 'POST') {
  // Do your thing
}

您可能不应该使用字符串作为方法类型 - 请改用常量。