Skip to content

Commit

Permalink
feat: added support for simple observable on mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
mbret committed Nov 30, 2023
1 parent ddff71f commit 680346d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 77 deletions.
9 changes: 8 additions & 1 deletion src/lib/queries/client/mutations/createMutationRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,14 @@ export const createMutationRunner = <T, MutationArg>({
mutationsRunning$.next(mutationsRunning$.getValue() + 1)
}),
switchOperator(({ args, options }) => {
const queryRunner$ = defer(() => from(options.mutationFn(args))).pipe(
const mutationFn = options.mutationFn

const mutationFnObservable =
typeof mutationFn === "function"
? defer(() => from(mutationFn(args)))
: mutationFn

const queryRunner$ = mutationFnObservable.pipe(
retryOnError(options),
take(1),
map((data) => ({ data, isError: false })),
Expand Down
4 changes: 4 additions & 0 deletions src/lib/queries/client/mutations/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export type MutationStatus = "idle" | "pending" | "success" | "error"

export type MutationKey = unknown[]

/**
* @todo this should be used in a lot of place so we can probably make a helper for that
*/
export interface MutationFilters {
/**
* Match mutation key exactly
Expand Down Expand Up @@ -60,6 +63,7 @@ export interface MutationObservedResult<R> extends MutationResult<R> {
}

export type MutationFn<T, MutationArg> =
| Observable<T>
| ((arg: MutationArg) => Promise<T>)
| ((arg: MutationArg) => Observable<T>)

Expand Down
125 changes: 49 additions & 76 deletions src/lib/queries/react/mutations/useMutationState.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
setActTimeout,
sleep
} from "../../../../tests/utils"
import { delay, of } from "rxjs"

describe("useIsMutating", () => {
it("should return the number of fetching mutations", async () => {
Expand Down Expand Up @@ -63,6 +64,54 @@ describe("useIsMutating", () => {
}, {})
})

it("should return the number of fetching observables mutations", async () => {
const isMutatings: number[] = []
const queryClient = createQueryClient()

const mutation2 = of("data").pipe(delay(50))

function IsMutating() {
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
const isMutating = useIsMutating()
isMutatings.push(isMutating)
return null
}

function Mutations() {
const { mutate: mutate1 } = useMutation({
mutationKey: ["mutation1"],
mutationFn: () => of("data").pipe(delay(150))
})
const { mutate: mutate2 } = useMutation({
mutationKey: ["mutation2"],
mutationFn: mutation2
})

React.useEffect(() => {
mutate1()
setActTimeout(() => {
mutate2()
}, 50)
}, [mutate1, mutate2])

return null
}

function Page() {
return (
<div>
<IsMutating />
<Mutations />
</div>
)
}

renderWithClient(queryClient, <Page />)
await waitFor(() => {
expect(isMutatings).toEqual([0, 1, 2, 1, 0])
}, {})
})

it("should filter correctly by mutationKey", async () => {
const isMutatings: number[] = []
const queryClient = createQueryClient()
Expand Down Expand Up @@ -184,79 +233,3 @@ describe("useIsMutating", () => {
await waitFor(() => rendered.getByText("mutating: 1"))
})
})

// describe('useMutationState', () => {
// describe('types', () => {
// it('should default to QueryState', () => {
// doNotExecute(() => {
// const result = useMutationState({
// filters: { status: 'pending' },
// })

// expectTypeOf(result).toEqualTypeOf<Array<MutationState>>()
// })
// })
// it('should infer with select', () => {
// doNotExecute(() => {
// const result = useMutationState({
// filters: { status: 'pending' },
// select: (mutation) => mutation.state.status,
// })

// expectTypeOf(result).toEqualTypeOf<Array<MutationStatus>>()
// })
// })
// })
// it('should return variables after calling mutate', async () => {
// const queryClient = createQueryClient()
// const variables: Array<Array<unknown>> = []
// const mutationKey = ['mutation']

// function Variables() {
// variables.push(
// useMutationState({
// filters: { mutationKey, status: 'pending' },
// select: (mutation) => mutation.state.variables,
// }),
// )

// return null
// }

// function Mutate() {
// const { mutate, data } = useMutation({
// mutationKey,
// mutationFn: async (input: number) => {
// await sleep(150)
// return 'data' + input
// },
// })

// return (
// <div>
// data: {data ?? 'null'}
// <button onClick={() => mutate(1)}>mutate</button>
// </div>
// )
// }

// function Page() {
// return (
// <div>
// <Variables />
// <Mutate />
// </div>
// )
// }

// const rendered = renderWithClient(queryClient, <Page />)

// await waitFor(() => rendered.getByText('data: null'))

// fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))

// await waitFor(() => rendered.getByText('data: data1'))

// expect(variables).toEqual([[], [1], []])
// })
// })

0 comments on commit 680346d

Please sign in to comment.