微调加载Redux
问题描述:
Redux中做某种旋转指示器的理想方式是什么?微调加载Redux
假设我有一个名为Things
的REST API。在React组件中,我有Thing Card
,Thing Card List
和Add 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
}
}
};
貌似错误的做法
答
如果你只是想知道如果的请求待处理并且什么方法(GET/POST/PUT /删除)正在使用,您可以将方法类型与其余状态一起存储,例如:
{
data: [],
isPending: true,
method: 'POST',
isSuccess: false,
isError: false,
error: undefined
}
然后你就可以在你的组件检查它,e.g:
const { isPending, method } = this.state;
if (isPending && method === 'POST') {
// Do your thing
}
你可能不应该使用的方法类型的字符串,但 - 用一个常量。
哦哇,这是完全有道理.......这样一个明显的解决方案!从来没有想过它!谢谢! –
很高兴帮助!如果没有其他东西,请标记为正确。 – tobiasandersen