更新我的rtk asyncthunk中的特定对象数据

huangapple go评论72阅读模式
英文:

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);
})

huangapple
  • 本文由 发表于 2023年6月8日 10:51:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76428299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定