React + Redux PUT api 请求编辑我的 redux 存储中的数据
React + Redux PUT api request to edit data in my redux store
我的应用程序使用 redux 将来自后端 API 的数据保存在 redux 存储实体 reducer 中,例如数据的 MEMBER 对象,它在 App 中的多个组件之间共享以显示成员详细信息。现在我正在实现 EditProfile 组件,它应该从表单中获取数据,将其作为 PUT 请求发送到后端 API 如果请求成功结束 (完成直到此处) 更新 redux 商店中的当前会员资料实体。我正在尝试找到类似 "best practice" 的内容来访问此 redux 商店更新。我已经实现了基本的 api 中间件(类似于 Redux 实际应用示例中的中间件),但我不完全确定,如何达到状态更新的部分。
我的后端 api return 在 PUT 请求后仅请求状态代码和原因(如果错误)或 memberId(如果成功)。我无法将后端端点更改为 return 新成员配置文件对象,因为我们的网络服务器之外还有另一个 "global" 服务器,它的工作方式与此服务器相同,我无法更改它。
所以我想我需要保留来自 Form (react-final-form) 的数据,如果包含 memberId 的成功响应(来自后端),请使用此数据更新当前的 Redux 存储实体(Member Profile) .
我正在考虑将更新请求数据保存到存储实体reducer中->使用像UPDATING_MEMBER_PROFILE这样的键并且id请求以成功结束,将这两个对象合并到一并清除 UPDATING_ 部分。请问大家有什么建议吗?
更新:
要在我的代码中调用 API,我会执行以下操作:
memberAction.js
export const updateProfile = values => ({
type: API,
payload: {
url: "/members/update",
method: "PUT",
data: values,
meta: {
label: MEMBER_PROFILE,
success: [], // action callbacks onSuccess
error: [] // action callbacks onError
}
}
});
然后我的 API 中间件负责 action.type === API 并为 API_REQUEST、API_SUCCESS 和 API_ERROR 生成操作类型,带有来自第一个 fetchProfile 操作的实体和标签。看起来像:
apiMiddleware.js
...getting Info from origin action about request here
next(action);
dispatch(apiRequest(entity, label));
return callApi(url, method, data)
.then(response => {
dispatch(apiSuccess(response.status, response, label));
dispatch(success(response)); // Dispatch callbacks...
})
.catch(error => {
dispatch(apiError(response.status, error, label));
dispatch(error(response)); // Dispatch callbacks...
});
在中间件服务器和分派另一个动作之后,我的 api reducer 将从 API 分配数据以按实体存储:
apiReducer.js
const apiEntitiesReducer = (state = {}, action) => {
switch (action.type) {
case API_REQUEST:
return {
...state,
[action.payload.label]: {
error: false,
data: null
}
};
case API_ERROR:
case API_SUCCESS:
return {
...state,
[action.payload.label]: {
error: action.isError,
data: action.payload.data
}
};
default:
return state;
}
};
这些只是为了保持简单的伪代码(我现在不使用 thunks...)。所以我需要在某个地方(可能在 api 中间件中)将临时数据保存到存储中(可能通过另一个操作)以通过这种方法达到我需要的东西?
你走在正确的道路上。尝试分派一个将请求发送到 API 的操作,然后(成功后)分派另一个操作来更新您的商店。类似的东西
profile.js:
export const updateProfile = newMemberProfile => { //your action, using thunk here
return dispatch => {
fetch(UPDATE_URL, {
method: "PUT",
body: JSON.stringify(newMemberProfile),
})
.catch(err => {
console.log(err);
alert("Profile update failed, please try again!");
})
.then(res => {
dispatch(memberProfileUpdated(newMemberProfile));
});
}
}
export const memberProfileUpdated = newMemberProfile => {
return {
type: UPDATING_MEMBER_PROFILE,
newMemberProfile
};
};
然后为这个常量添加一个化简器(为了清楚起见,将所有常量和化简器放在单独的文件中)
reducer.js:
const initialState = {
memberProfile: null,
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATING_MEMBER_PROFILE:
return {
...state,
memberProfile: action.newMemberProfile
};
default:
return state;
}
};
export default reducer;
不要忘记在您的配置中注册您的减速器!
希望对您有所帮助!
我的应用程序使用 redux 将来自后端 API 的数据保存在 redux 存储实体 reducer 中,例如数据的 MEMBER 对象,它在 App 中的多个组件之间共享以显示成员详细信息。现在我正在实现 EditProfile 组件,它应该从表单中获取数据,将其作为 PUT 请求发送到后端 API 如果请求成功结束 (完成直到此处) 更新 redux 商店中的当前会员资料实体。我正在尝试找到类似 "best practice" 的内容来访问此 redux 商店更新。我已经实现了基本的 api 中间件(类似于 Redux 实际应用示例中的中间件),但我不完全确定,如何达到状态更新的部分。
我的后端 api return 在 PUT 请求后仅请求状态代码和原因(如果错误)或 memberId(如果成功)。我无法将后端端点更改为 return 新成员配置文件对象,因为我们的网络服务器之外还有另一个 "global" 服务器,它的工作方式与此服务器相同,我无法更改它。
所以我想我需要保留来自 Form (react-final-form) 的数据,如果包含 memberId 的成功响应(来自后端),请使用此数据更新当前的 Redux 存储实体(Member Profile) .
我正在考虑将更新请求数据保存到存储实体reducer中->使用像UPDATING_MEMBER_PROFILE这样的键并且id请求以成功结束,将这两个对象合并到一并清除 UPDATING_ 部分。请问大家有什么建议吗?
更新:
要在我的代码中调用 API,我会执行以下操作:
memberAction.js
export const updateProfile = values => ({
type: API,
payload: {
url: "/members/update",
method: "PUT",
data: values,
meta: {
label: MEMBER_PROFILE,
success: [], // action callbacks onSuccess
error: [] // action callbacks onError
}
}
});
然后我的 API 中间件负责 action.type === API 并为 API_REQUEST、API_SUCCESS 和 API_ERROR 生成操作类型,带有来自第一个 fetchProfile 操作的实体和标签。看起来像:
apiMiddleware.js
...getting Info from origin action about request here
next(action);
dispatch(apiRequest(entity, label));
return callApi(url, method, data)
.then(response => {
dispatch(apiSuccess(response.status, response, label));
dispatch(success(response)); // Dispatch callbacks...
})
.catch(error => {
dispatch(apiError(response.status, error, label));
dispatch(error(response)); // Dispatch callbacks...
});
在中间件服务器和分派另一个动作之后,我的 api reducer 将从 API 分配数据以按实体存储:
apiReducer.js
const apiEntitiesReducer = (state = {}, action) => {
switch (action.type) {
case API_REQUEST:
return {
...state,
[action.payload.label]: {
error: false,
data: null
}
};
case API_ERROR:
case API_SUCCESS:
return {
...state,
[action.payload.label]: {
error: action.isError,
data: action.payload.data
}
};
default:
return state;
}
};
这些只是为了保持简单的伪代码(我现在不使用 thunks...)。所以我需要在某个地方(可能在 api 中间件中)将临时数据保存到存储中(可能通过另一个操作)以通过这种方法达到我需要的东西?
你走在正确的道路上。尝试分派一个将请求发送到 API 的操作,然后(成功后)分派另一个操作来更新您的商店。类似的东西
profile.js:
export const updateProfile = newMemberProfile => { //your action, using thunk here
return dispatch => {
fetch(UPDATE_URL, {
method: "PUT",
body: JSON.stringify(newMemberProfile),
})
.catch(err => {
console.log(err);
alert("Profile update failed, please try again!");
})
.then(res => {
dispatch(memberProfileUpdated(newMemberProfile));
});
}
}
export const memberProfileUpdated = newMemberProfile => {
return {
type: UPDATING_MEMBER_PROFILE,
newMemberProfile
};
};
然后为这个常量添加一个化简器(为了清楚起见,将所有常量和化简器放在单独的文件中) reducer.js:
const initialState = {
memberProfile: null,
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATING_MEMBER_PROFILE:
return {
...state,
memberProfile: action.newMemberProfile
};
default:
return state;
}
};
export default reducer;
不要忘记在您的配置中注册您的减速器! 希望对您有所帮助!