Ryan
Ryan8mo ago

Modify the payload before mutating

I have a specific mutation hook that is used all throughout my app, and inside of the hook I want to modify the payload before it is sent to the server (to read something from local storage and add it to payload). Is this possible? I can't seem to find a way to do this. There also isn't a way AFAIK to modify the mutationFn with the nextjs adapter. My only solution would be redefining mutate and mutateAsync that are modified to do this preprocessing. Thanks!
6 Replies
Nick
Nick8mo ago
What's the actual use case?
Ryan
Ryan8mo ago
I have a hook wrapped around this specific useMutation that is called from a few different places in my app. I need it to pass some UTM params stored in my local storage along with the payload, but don't want to have to remember to always include the params when I call the mutation. Ideally in the hook (within the mutate fn) I can add the utms
Nick
Nick8mo ago
If you have a custom hook why not just wrap the mutation function and return it? That way it’s all static typed Alternatively wouldn’t UTM params often be better to include as headers? You can easily attach them as headers from the client you create
Ryan
Ryan8mo ago
I would but I would need to separately wrap both mutate and mutateAsync since I would need to modify the payload on both. Yeah I have a few more non utm param things, like referral code etc.
Nick
Nick8mo ago
If you have some global middlewarish solution on the frontend, you would be modifying requests without any type safety. I would just wrap the 2 functions, it's safe and not that laborious
Ryan
Ryan8mo ago
I wouldn't be losing type safety necessarily, cause the items that I want to add in preprocessing are all optional items, so mutate would still infer its original payload type This is what I ended up doing.. not sure I like it though, also not 100% sure what the impications of using the ProxyClient is on the cache, if any.
export const useVerifyCode = () => {
const key = getQueryKey(trpc.auth.verifyCode);

const mutationFn = async (block: RouterInputs['auth']['verifyCode']) => {
const maybeReferralCode = storage.getReferrerCode();
const maybeUTM = storage.getUTM();
const utmObject = maybeUTM ? JSON.parse(maybeUTM) : {};
// safe parse with zod
const utmValidation = zodUtm.safeParse(utmObject);
const validatedUtm = utmValidation.success ? utmValidation.data : {};

const extendedBlock = {
...block,
referralCode: maybeReferralCode,
...validatedUtm,
};

return trcpProxyClient.auth.verifyCode.mutate(extendedBlock);
};

const mutation = useMutation({
mutationFn,
mutationKey: key,
onSuccess(data) {
storage.setAccessToken(data.accessToken);
storage.setRefreshToken(data.refreshToken);

identify(data);
},
});

return mutation;
};
export const useVerifyCode = () => {
const key = getQueryKey(trpc.auth.verifyCode);

const mutationFn = async (block: RouterInputs['auth']['verifyCode']) => {
const maybeReferralCode = storage.getReferrerCode();
const maybeUTM = storage.getUTM();
const utmObject = maybeUTM ? JSON.parse(maybeUTM) : {};
// safe parse with zod
const utmValidation = zodUtm.safeParse(utmObject);
const validatedUtm = utmValidation.success ? utmValidation.data : {};

const extendedBlock = {
...block,
referralCode: maybeReferralCode,
...validatedUtm,
};

return trcpProxyClient.auth.verifyCode.mutate(extendedBlock);
};

const mutation = useMutation({
mutationFn,
mutationKey: key,
onSuccess(data) {
storage.setAccessToken(data.accessToken);
storage.setRefreshToken(data.refreshToken);

identify(data);
},
});

return mutation;
};