英文:
Updating a specific object data in my rtk asyncthunk
问题
以下是您要翻译的代码部分:
I am new to rtk and immer. I have a problem regarding updating my state with my redux. Lets say when I logging in my user, I will store my user's data in redux with these kind of structure:
data = {
"user_profile" : {
"name": "John Doe",
"Token": "12345678"
},
"basic_information": {
"primary_information": {
"sex": "MALE",
"age": 30,
"photo": "test.png"
}
}
}
now when i will call my update api, then my api returns something like these updated values:
updated_data = {
"user_profile" : {
"name": "John Test",
},
"basic_information": {
"primary_information": {
"sex": "FEMALE",
"age": 27,
}
}
}
I want to update my current state based on my api update state values, but i want the token will remain and other data that i didnt update.
Here is what i did/tried with the asyncthunk rtk.
I have a slice:
export const updatePrimaryInformation = createAsyncThunk(
"profile/primary_info",
async (arg, { rejectWithValue }) => {
const { body, headers } = arg;
try {
const updateRequest = await commonPutRequest({
body,
headers,
url: "http://localhost:8000/api/accounts_app/primary_information",
});
if (updateRequest) {
return updateRequest;
} else {
throw new Error(updateRequest.message);
}
} catch (err) {
return rejectWithValue(err.message);
}
}
);
// loading: 'idle' | 'pending' | 'succeeded' | 'failed'
const initialState = {
data: {},
loading: "idle",
message: "",
};
const authenticateSlice = createSlice({
name: "auth",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
//login
.addCase(fetchUserLogin.pending, (state) => {
state.loading = "pending";
})
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = action.payload;
})
.addCase(fetchUserLogin.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
//logout
.addCase(logoutUser.pending, (state) => {
state.loading = "pending";
})
.addCase(logoutUser.fulfilled, (state, action) => {
return initialState;
})
.addCase(logoutUser.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
//updatePrimaryInfo
.addCase(updatePrimaryInformation.pending, (state) => {
state.loading = "pending";
})
.addCase(updatePrimaryInformation.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data.basic_information.primary_information = action.payload.basic_information.primary_information;
})
.addCase(updatePrimaryInformation.rejected, (state, action) => {
state.loading = "failed";
// state.message = action.payload;
});
// .addCase(userLogout, (state) => {
// return initialState;
// });
},
});
希望这能帮助您理解代码的翻译。如果您有任何其他问题,请随时提出。
英文:
I am new to rtk and immer. I have a problem regarding updating my state with my redux. Lets say when I logging in my user, I will store my user's data in redux with these kind of structure:
data = {
"user_profile" : {
"name": "John Doe",
"Token": "12345678"
},
"basic_information": {
"primary_information": {
"sex": "MALE",
"age": 30,
"photo": "test.png"
}
}
}
now when i will call my update api, then my api returns something like these updated values:
updated_data = {
"user_profile" : {
"name": "John Test",
},
"basic_information": {
"primary_information": {
"sex": "FEMALE",
"age": 27,
}
}
}
I want to update my current state based on my api update state values, but i want the token will remain and other data that i didnt update.
Here is what i did/tried with the asyncthunk rtk.
I have a slice:
export const updatePrimaryInformation = createAsyncThunk(
"profile/primary_info",
async (arg, { rejectWithValue }) => {
const { body, headers } = arg;
try {
const updateRequest = await commonPutRequest({
body,
headers,
url: "http://localhost:8000/api/accounts_app/primary_information",
});
if (updateRequest) {
return updateRequest;
} else {
throw new Error(updateRequest.message);
}
} catch (err) {
return rejectWithValue(err.message);
}
}
);
// loading: 'idle' | 'pending' | 'succeeded' | 'failed'
const initialState = {
data: {},
loading: "idle",
message: "",
};
const authenticateSlice = createSlice({
name: "auth",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
//login
.addCase(fetchUserLogin.pending, (state) => {
state.loading = "pending";
})
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = action.payload;
})
.addCase(fetchUserLogin.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
//logout
.addCase(logoutUser.pending, (state) => {
state.loading = "pending";
})
.addCase(logoutUser.fulfilled, (state, action) => {
return initialState;
})
.addCase(logoutUser.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
//updatePrimaryInfo
.addCase(updatePrimaryInformation.pending, (state) => {
state.loading = "pending";
})
.addCase(updatePrimaryInformation.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data.basic_information.primary_information = action.payload.basic_information.primary_information;
})
.addCase(updatePrimaryInformation.rejected, (state, action) => {
state.loading = "failed";
// state.message = action.payload;
});
// .addCase(userLogout, (state) => {
// return initialState;
// });
},
});
答案1
得分: 0
Redux或immer默认情况下没有这个功能。
听起来你想要执行lodash的merge
操作。这个操作将两个对象合并在一起,只插入未定义的键。
你可以安装lodash或查看该函数并重新实现它。Lodash还支持部分导入。
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = _.merge(action.payload, state.data);
})
英文:
Redux or immer doesn't have this functionality out of the box.
It sounds like you want to do the merge
operation from lodash. This merges two objects together by only inserting undefined keys.
You can install lodash or look at the function and reimplment it. Lodash also has partial imports.
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = _.merge(action.payload, state.data);
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论