我想允许用户多次将同一服务器项添加到页面中(标识:5)。为了在我们的应用程序中跟踪这些项目,我们需要为每个实例生成一个唯一的ID。
我们的商品具有关系数据,因此出于性能方面的考虑,我们可以在redux存储中对API响应进行规范化。
type Item = { id: string; }
type Sku = { id: string; }
type AppStore = {
items: { [id: string]: Items },
skus: { [id: string]: Skus },
itemSkus: { [id: string]: string[] },
}
使用此API
export interface IAPIResponse<T> {
data?: T;
errors?: string[];
}
type IAPIItem = {
id: string;
skus: Array<{
id: string;
}>;
}
在典型的redux-thunk动作创建者中请求数据:
export const addItem = () => async (dispatch) => {
dispatch(startedAddItem());
try {
const response = await get <IAPIResponse<IAPIItem>>('/get/item/5');
dispatch(succeededAddItem(response));
} catch (error) {
console.error('Error', error);
dispatch(failedAddItem(error));
}
};
并使用相关数据填充我们的异径管:
// items reducer
case ItemAction.addSucceeded:
const apiItem = getApiResource(action.payload);
const apiErrors = getApiErrors(action.payload);
if (apiErrors) // Handle errors in state
if (apiItem) {
const item = buildItem(apiItem);
return {
...state,
[item.id]: item,
}
}
break;
// skus reducer
case ItemAction.addSucceeded:
const apiItem = getApiResource(action.payload);
const apiErrors = getApiErrors(action.payload);
if (apiErrors) // Handle errors in state
if (apiItem) {
const skus = buildSkus(apiItem.skus);
const indexedSkus = { ...skus.map(s => ({ [s.id]: s })) };
return {
...state,
...indexedSkus,
}
}
break;
// itemSkus reducer
case ItemAction.addSucceeded:
const apiItem = getApiResource(action.payload);
const apiErrors = getApiErrors(action.payload);
if (apiErrors) // Handle errors in state
if (apiItem) {
const item = buildLineItem(apiItem);
const skus = buildSkus(apiItem.skus);
return {
[item.id]: skus.map(s => s.id),
}
}
break;
在这种模式下,我们无法可靠地为Item和Skus生成相同的唯一ID,因为响应是在多个reducer中解析的。 Redux建议我们必须先生成唯一的ID,然后才能将其击中减速器。
问题:我如何适应这种模式以在化简器之前解析响应,同时保持灵活性以读取嵌套的api数据并解析化简器中的响应主体错误?
答案 0 :(得分:1)
在进一步讨论Discord之后,OP提供了以下关键信息:
这里实际上只有一个数据流
- 当用户单击“添加轮胎”(
/tire/add/5
)时,React应用程序可以从数据库请求轮胎。- 他们可以多次请求相同的轮胎
- 然后他们可以修改该轮胎的每个实例以具有独特的属性
- 点击“保存”会将汽车及其轮胎发送到
/car/save
我的答案:
/tire/add
API端点每次发送响应时都可以生成一个UUID。或者,在客户端:
const addTire = (sku, otherData) => {
const response = await post(`/tire/add/${sku}`, otherData);
response.data.id = uuid();
dispatch(tireAdded(response.data));
}
或替代,尤其是在使用RTK的情况下:
const tiresSlice = createSlice({
name: "tires",
initialState,
reducers: {
tireAdded: {
reducer(state, action) {
// whatever here
},
prepare(tireData) {
return {
payload: {...tireData, id: uiud()}
}
}
}
}
})
总体: