Skip to content

Commit

Permalink
Merge pull request #139 from IdoPesok/undefined-data-bug
Browse files Browse the repository at this point in the history
handle undefined data properly, fixes #138
  • Loading branch information
IdoPesok authored Jun 22, 2024
2 parents 0ba650d + 0c7f25a commit db5916e
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-apples-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"zsa-react": patch
---

Fix isSuccess with undefined data
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ jobs:

- name: Test
run: npm run test

- name: Typecheck
run: npm run typecheck
9 changes: 8 additions & 1 deletion packages/zsa-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@ export const useServerAction = <
if (oldResult.status === "filled") {
setResult(oldResult.result)
} else {
setResult({ error: err, isError: true, data: undefined })
setResult({
error: err,
isError: true,
data: undefined,
isSuccess: false,
})
}

// clear the old data
Expand All @@ -162,6 +167,7 @@ export const useServerAction = <
isError: false,
error: undefined,
data: data ?? undefined,
isSuccess: true,
}

setResult(res)
Expand Down Expand Up @@ -234,6 +240,7 @@ export const useServerAction = <
isError: false,
error: undefined,
data: data ?? undefined,
isSuccess: true,
})
},
[execute]
Expand Down
11 changes: 7 additions & 4 deletions packages/zsa-react/src/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
*/
export type TInnerResult<TServerAction extends TAnyZodSafeFunctionHandler> = {
isError: boolean
isSuccess: boolean
error: undefined | inferServerActionError<TServerAction>
data: undefined | inferServerActionReturnData<TServerAction>
}
Expand Down Expand Up @@ -101,22 +102,22 @@ export const calculateResultFromState = <
isSuccess: false,
status: "pending",
}
} else if (isPending && oldResult.status === "filled" && result.data) {
} else if (isPending && oldResult.status === "filled" && result.isSuccess) {
return {
isPending: true,
isOptimistic: true,
data: result.data,
data: result.data as any,
isError: false,
error: undefined,
isSuccess: false,
status: "pending",
}
} else if (!result.isError && result.data) {
} else if (result.isSuccess) {
// success state
return {
isPending: false,
isOptimistic: false,
data: result.data,
data: result.data as any,
isError: false,
error: undefined,
isSuccess: true,
Expand Down Expand Up @@ -156,12 +157,14 @@ export const getEmptyResult = <
? // if there is no initial data
{
isError: false,
isSuccess: false,
error: undefined,
data: undefined,
}
: {
// if there is initial data
isError: false,
isSuccess: true,
error: undefined,
data: initialData,
}
Expand Down
25 changes: 25 additions & 0 deletions tests/jest/__tests__/client.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import OptimisticUpdatesUI from "app/tests/client/optimistic-updates/page"
import ResetUI from "app/tests/client/reset/page"
import RetryStatesUI from "app/tests/client/retry-states/page"
import StatesUI from "app/tests/client/states/page"
import UndefinedSuccessActionUI from "app/tests/client/undefined-success-action/page"
import InfiniteQueryUI from "app/tests/client/use-server-action-infinite-query/page"
import MutationUI from "app/tests/client/use-server-action-mutation/page"
import QueryUI from "app/tests/client/use-server-action-query/page"
Expand Down Expand Up @@ -46,6 +47,30 @@ describe("client", () => {
})
})

describe.only("undefined success execute", () => {
it('basic useServerAction that returns "hello world"', async () => {
render(<UndefinedSuccessActionUI />)

let resultElement = screen.getByRole(CLIENT_TEST_DATA.roles.result)

expect(resultElement).toHaveTextContent("false")

// Try using getByText if getByRole is not working
const invokeButton = screen.getByRole(CLIENT_TEST_DATA.roles.invoke)
fireEvent.click(invokeButton)

await waitFor(() => {
resultElement = screen.getByRole(CLIENT_TEST_DATA.roles.result)
expect(resultElement).toHaveTextContent(CLIENT_TEST_DATA.loadingMessage)
})

await waitFor(() => {
resultElement = screen.getByRole(CLIENT_TEST_DATA.roles.result)
expect(resultElement).toHaveTextContent("true")
})
})
})

describe("useServerAction execute with procedure context", () => {
it("useServerAction that returns procedure context", async () => {
;(cookies as jest.Mock).mockReturnValue({
Expand Down
29 changes: 29 additions & 0 deletions tests/jest/app/tests/client/undefined-success-action/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use client"

import { undefinedSuccessAction } from "server/actions"
import { CLIENT_TEST_DATA } from "server/data"
import { useServerAction } from "zsa-react"

export default function UndefinedSuccessActionUI() {
const { isPending, execute, isSuccess } = useServerAction(
undefinedSuccessAction
)

return (
<div>
<button
role="invoke"
onClick={async () => {
await execute({ ms: CLIENT_TEST_DATA.sleep })
}}
>
Invoke action
</button>
<div role="result">
{isPending
? CLIENT_TEST_DATA.loadingMessage
: JSON.stringify(isSuccess)}
</div>
</div>
)
}
6 changes: 6 additions & 0 deletions tests/jest/server/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ export const resetAction = publicAction.handler(async () => {
return CLIENT_TEST_DATA.resultMessages.resetAction
})

export const undefinedSuccessAction = publicAction
.input(z.object({ ms: z.number() }))
.handler(async ({ input: { ms } }) => {
await sleep(ms)
})

export const loadingHelloWorldAction = publicAction
.input(z.object({ ms: z.number() }))
.handler(async ({ input: { ms } }) => {
Expand Down

0 comments on commit db5916e

Please sign in to comment.