Skip to content

Commit

Permalink
feat: add optimistic update to contributions
Browse files Browse the repository at this point in the history
  • Loading branch information
dominik-stumpf committed Aug 9, 2024
1 parent b950348 commit 115a695
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 20 deletions.
36 changes: 27 additions & 9 deletions src/app/(marketing)/profile/_hooks/useCreateContribution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type EditProfilePayload = Schemas["ContributionUpdate"]
export const useCreateContribution = () => {
const { toast } = useToast()
const { data: profile } = useProfile()
const contribution = useContribution()
const contributions = useContribution()

const update = async (signedValidation: SignedValidation) => {
return fetcher(
Expand All @@ -24,16 +24,34 @@ export const useCreateContribution = () => {
}

const submitWithSign = useSubmitWithSign<Schemas["Contribution"]>(update, {
onSuccess: (response) => {
contribution.mutate(
(prev) => {
// WARNING: should we validate here?
if (!prev) return
prev.push(response)
return prev
onOptimistic: (response, payload) => {
if (!profile?.userId) return
contributions.mutate(
async () => {
if (!contributions.data) return
const contribution = await response
contributions.data[contributions.data.findIndex(({ id }) => id === -1)] =
contribution
// contributions.data.push(await response)
return contributions.data
},
{ revalidate: false }
{
revalidate: false,
rollbackOnError: true,
optimisticData: () => {
const fakeContribution: Schemas["Contribution"] = {
...(payload as EditProfilePayload),
id: -1,
profileId: profile.userId,
}
if (!contributions.data) return [fakeContribution]
contributions.data.push(fakeContribution)
return contributions.data
},
}
)
},
onSuccess: (response) => {
revalidateContribution()
toast({
variant: "success",
Expand Down
24 changes: 16 additions & 8 deletions src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const useDeleteContribution = ({
}: { contributionId: Schemas["Contribution"]["id"] }) => {
const { toast } = useToast()
const { data: profile } = useProfile()
const contribution = useContribution()
const contributions = useContribution()

const update = async (signedValidation: SignedValidation) => {
return fetcher(
Expand All @@ -24,15 +24,23 @@ export const useDeleteContribution = ({
}

const submitWithSign = useSubmitWithSign<object>(update, {
onSuccess: () => {
contribution.mutate(
(prev) => {
if (!prev || !contribution.data) return
// WARNING: should we validate here?
return prev.filter((p) => p.id !== contributionId)
onOptimistic: (response) => {
contributions.mutate(
async () => {
await response
return contributions.data?.filter((p) => p.id !== contributionId)
},
{ revalidate: false }
{
revalidate: false,
rollbackOnError: true,
optimisticData: () => {
if (!contributions.data) return []
return contributions.data.filter((p) => p.id !== contributionId)
},
}
)
},
onSuccess: () => {
revalidateContribution()
toast({
variant: "success",
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useSubmit/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type MessageParams = {
export type UseSubmitOptions<ResponseType = void> = {
onSuccess?: (response: ResponseType) => void
onError?: (error: any) => void
onOptimistic?: (response: Promise<ResponseType>, payload: any) => void

// Use catefully! If this is set to true, a .onSubmit() call can reject!
allowThrow?: boolean
Expand Down
13 changes: 10 additions & 3 deletions src/hooks/useSubmit/useSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ type FetcherFunction<ResponseType> = ({

const useSubmit = <DataType, ResponseType>(
fetch: (data?: DataType) => Promise<ResponseType>,
{ onSuccess, onError, allowThrow }: UseSubmitOptions<ResponseType> = {}
{
onSuccess,
onError,
allowThrow,
onOptimistic,
}: UseSubmitOptions<ResponseType, DataType> = {}
) => {
const [isLoading, setIsLoading] = useState<boolean>(false)
const [error, setError] = useState<any>(undefined)
Expand All @@ -31,7 +36,9 @@ const useSubmit = <DataType, ResponseType>(
(data?: DataType): Promise<ResponseType> => {
setIsLoading(true)
setError(undefined)
return fetch(data)
const response = fetch(data)
onOptimistic?.(response, data)
return response
.then((d) => {
onSuccess?.(d)
setResponse(d)
Expand All @@ -47,7 +54,7 @@ const useSubmit = <DataType, ResponseType>(
})
.finally(() => setIsLoading(false))
},
[allowThrow, fetch, onError, onSuccess]
[allowThrow, fetch, onError, onSuccess, onOptimistic]
)

return {
Expand Down

0 comments on commit 115a695

Please sign in to comment.