Lautaro_dapin
Lautaro_dapin
TtRPC
Created by Lautaro_dapin on 12/10/2023 in #❓-help
Discriminated output based on discrimiated input
I have this function which works correctly by itself, but when i put it on trpc, the output doesn't get inffered correctly based o the input
type GetFarmsInput = {
growerId?: number;
provider?: string;
leafUserId?: string;
page?: number;
size?: number;
} & ({withFields: true} | {withFields?: false | undefined});

type GetFarmsOutput<T extends GetFarmsInput> = T extends {withFields: true}
? FarmSchema[]
: (FarmSchema & {fields: FieldSchema[]})[];

export async function getFarms<T extends GetFarmsInput>(input: T): Promise<GetFarmsOutput<T>>;
export async function getFarms<T extends GetFarmsInput>(input: T) {
const {withFields, ...options} = input;
const searchParams = stringify(options);
const response = await endpoint(`/services/fields/api/farms?${searchParams.toString()}`, 'GET');
if (!response.ok) {
throw Error(`Couldn't get the farms`, {cause: await response.json()});
}
const farms = await farmsSchema.parseAsync(await response.json());
if (withFields) {
return await Promise.all(
farms.map(async (farm) => {
const fieldsMap = mapToIds(
await getAllFields({farmId: farm.id, size: 100, leafUserId: options.leafUserId})
);
return {
...farm,
fields: farm.fieldIds.map((id) => fieldsMap.get(id)),
};
})
);
}
return farms;
}
type GetFarmsInput = {
growerId?: number;
provider?: string;
leafUserId?: string;
page?: number;
size?: number;
} & ({withFields: true} | {withFields?: false | undefined});

type GetFarmsOutput<T extends GetFarmsInput> = T extends {withFields: true}
? FarmSchema[]
: (FarmSchema & {fields: FieldSchema[]})[];

export async function getFarms<T extends GetFarmsInput>(input: T): Promise<GetFarmsOutput<T>>;
export async function getFarms<T extends GetFarmsInput>(input: T) {
const {withFields, ...options} = input;
const searchParams = stringify(options);
const response = await endpoint(`/services/fields/api/farms?${searchParams.toString()}`, 'GET');
if (!response.ok) {
throw Error(`Couldn't get the farms`, {cause: await response.json()});
}
const farms = await farmsSchema.parseAsync(await response.json());
if (withFields) {
return await Promise.all(
farms.map(async (farm) => {
const fieldsMap = mapToIds(
await getAllFields({farmId: farm.id, size: 100, leafUserId: options.leafUserId})
);
return {
...farm,
fields: farm.fieldIds.map((id) => fieldsMap.get(id)),
};
})
);
}
return farms;
}
2 replies
TtRPC
Created by Lautaro_dapin on 6/11/2023 in #❓-help
Optimistic update on infinite query
Node 18.12.1 with pnpm trpc v 10.28.1 I have the following query to render a list of posts
// List of posts
export default function ListPage(){
const router = useRouter()
const q = router.query.q as string || ''
const {data} = api.post.feed.useInfiniteQuery({q}, {
getNextPageParam: lastPage => lastPage.nextCursor,
})
const posts = data?.pages.flatMap(page => page.items)

return (
<>
{posts.map(post => <Post post={post}/> )}
</>
)
}
// List of posts
export default function ListPage(){
const router = useRouter()
const q = router.query.q as string || ''
const {data} = api.post.feed.useInfiniteQuery({q}, {
getNextPageParam: lastPage => lastPage.nextCursor,
})
const posts = data?.pages.flatMap(page => page.items)

return (
<>
{posts.map(post => <Post post={post}/> )}
</>
)
}
Then inside the Post component i have the following muutation to toggle a like server state But for some reason when i want to update the cache for an optimistic update the cache is always empty, idk why
const utils = api.useContext()
const toggleLikeMutation = api.post.toggleLikePost.useMutation({
onMutate: async () => {
const snapshot = utils.post.feed.getInfiniteData({q: ''})
console.log({snapshot}) // <---- EMPTY
if (!snapshot) return {snapshot}
utils.post.feed.setInfiniteData({}, () => {
return {
...snapshot,
pages: snapshot.pages.map(page => {
return {
...page,
items: page.items.map(post => {
if (post.id !== id) return post
return {
...post,
liked: !post.liked
}
})
}
})
}
})
return {
snapshot
}
},

onError: (error, {postId}, ctx) => {
ctx?.snapshot && utils.post.feed.setInfiniteData({}, () => ctx.snapshot)
},

async onSuccess() {
await utils.post.feed.invalidate()

}
})
const utils = api.useContext()
const toggleLikeMutation = api.post.toggleLikePost.useMutation({
onMutate: async () => {
const snapshot = utils.post.feed.getInfiniteData({q: ''})
console.log({snapshot}) // <---- EMPTY
if (!snapshot) return {snapshot}
utils.post.feed.setInfiniteData({}, () => {
return {
...snapshot,
pages: snapshot.pages.map(page => {
return {
...page,
items: page.items.map(post => {
if (post.id !== id) return post
return {
...post,
liked: !post.liked
}
})
}
})
}
})
return {
snapshot
}
},

onError: (error, {postId}, ctx) => {
ctx?.snapshot && utils.post.feed.setInfiniteData({}, () => ctx.snapshot)
},

async onSuccess() {
await utils.post.feed.invalidate()

}
})
2 replies