-
Notifications
You must be signed in to change notification settings - Fork 0
02: convex package #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,22 @@ | ||
| import { Button } from "@workspace/ui/components/button" | ||
| import { add } from "@workspace/math/add" | ||
| "use client" | ||
|
|
||
| import { useMutation, useQuery } from 'convex/react' | ||
| import { api } from '@workspace/backend/_generated/api' | ||
| import { Button } from '@workspace/ui/components/button' | ||
|
|
||
| export default function Page() { | ||
|
|
||
| const users = useQuery(api.users.getMany) | ||
| const addUser = useMutation(api.users.add) | ||
|
|
||
|
|
||
| return ( | ||
| <div className="flex min-h-svh p-6"> | ||
| <div className="flex max-w-md min-w-0 flex-col gap-4 text-sm leading-loose"> | ||
| <div> | ||
| <h1 className="font-medium">Project ready!</h1> | ||
| <p>{add(1, 2)}</p> | ||
| <Button className="mt-2">Button</Button> | ||
| </div> | ||
| <div className="text-muted-foreground font-mono text-xs"> | ||
| (Press <kbd>d</kbd> to toggle dark mode) | ||
| </div> | ||
| </div> | ||
| <div className="flex flex-col items-center justify-center min-h-svh"> | ||
| <Button onClick={()=>addUser()}>Add User</Button> | ||
| <p>apps/Web</p> | ||
| <div className='max-w-sm w-full mx-auto'> | ||
| {JSON.stringify(users, null , 2)} | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||||||||||||||
| "use client" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import * as React from "react" | ||||||||||||||||||||||
| import { ConvexProvider, ConvexReactClient } from "convex/react"; | ||||||||||||||||||||||
| // import { ConvexProviderWithClerk } from 'convex/react-clerk' | ||||||||||||||||||||||
| // import { useAuth } from '@clerk/nextjs' | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // if (!process.env.NEXT_PUBLIC_CONVEX_URL) { | ||||||||||||||||||||||
| // throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file') | ||||||||||||||||||||||
| // } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || ""); | ||||||||||||||||||||||
|
Comment on lines
+8
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enable environment variable validation or use non-null assertion. The fallback to an empty string ( 🔧 Proposed fix: enable validation-// if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
-// throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file')
-// }
+if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
+ throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file')
+}
-const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || "");
+const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export function Providers({ children }: { children: React.ReactNode }) { | ||||||||||||||||||||||
| return ( | ||||||||||||||||||||||
| <ConvexProvider client={convex}>{children}</ConvexProvider> | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // <ConvexProviderWithClerk client={convex} useAuth={useAuth}> | ||||||||||||||||||||||
| // {children} | ||||||||||||||||||||||
| // </ConvexProviderWithClerk> | ||||||||||||||||||||||
| ); | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,21 @@ | ||
| import { Button } from "@workspace/ui/components/button" | ||
| import {add } from "@workspace/math/add" | ||
| import { Input } from "@workspace/ui/components/input" | ||
| "use client" | ||
|
|
||
| import { useMutation, useQuery } from 'convex/react' | ||
| import { api } from '@workspace/backend/_generated/api' | ||
| import { Button } from '@workspace/ui/components/button' | ||
|
|
||
| export default function Page() { | ||
|
|
||
| const users = useQuery(api.users.getMany) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle loading state for
🔧 Proposed fix: add loading state const users = useQuery(api.users.getMany)
const addUser = useMutation(api.users.add)
return (
<div className="flex flex-col items-center justify-center min-h-svh">
<Button onClick={()=>addUser()}>Add User</Button>
<p>apps/widget</p>
<div className='max-w-sm w-full mx-auto'>
- {JSON.stringify(users, null , 2)}
+ {users === undefined ? "Loading..." : JSON.stringify(users, null, 2)}
</div>
</div>
)Also applies to: 17-17 🤖 Prompt for AI Agents |
||
| const addUser = useMutation(api.users.add) | ||
|
|
||
| return ( | ||
| <div className="flex min-h-svh p-6"> | ||
| <div className="flex max-w-md min-w-0 flex-col gap-4 text-sm leading-loose"> | ||
| <div> | ||
| <h1 className="font-medium">Project ready!</h1> | ||
| <p>You may now add components and start building.</p> | ||
| <p>We've already added the button component for you.</p> | ||
| <Button className="mt-2">Button</Button> | ||
| </div> | ||
| <div className="text-muted-foreground font-mono text-xs"> | ||
| (Press <kbd>d</kbd> to toggle dark mode) | ||
| <p>{add(1, 2)}</p> | ||
| </div> | ||
| <Input/> | ||
| </div> | ||
| <div className="flex flex-col items-center justify-center min-h-svh"> | ||
| <Button onClick={()=>addUser()}>Add User</Button> | ||
| <p>apps/widget</p> | ||
| <div className='max-w-sm w-full mx-auto'> | ||
| {JSON.stringify(users, null , 2)} | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||||||||||||||
| "use client" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import * as React from "react" | ||||||||||||||||||||||
| import { ConvexProvider, ConvexReactClient } from "convex/react"; | ||||||||||||||||||||||
| // import { ConvexProviderWithClerk } from 'convex/react-clerk' | ||||||||||||||||||||||
| // import { useAuth } from '@clerk/nextjs' | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // if (!process.env.NEXT_PUBLIC_CONVEX_URL) { | ||||||||||||||||||||||
| // throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file') | ||||||||||||||||||||||
| // } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || ""); | ||||||||||||||||||||||
|
Comment on lines
+8
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enable environment variable validation or use non-null assertion. Same issue as 🔧 Proposed fix: enable validation-// if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
-// throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file')
-// }
+if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
+ throw new Error('Missing NEXT_PUBLIC_CONVEX_URL in your .env file')
+}
-const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || "");
+const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export function Providers({ children }: { children: React.ReactNode }) { | ||||||||||||||||||||||
| return ( | ||||||||||||||||||||||
| <ConvexProvider client={convex}>{children}</ConvexProvider> | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // <ConvexProviderWithClerk client={convex} useAuth={useAuth}> | ||||||||||||||||||||||
| // {children} | ||||||||||||||||||||||
| // </ConvexProviderWithClerk> | ||||||||||||||||||||||
| ); | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
|
|
||
| .env.local |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: harshshukla2807/echo
Length of output: 85
🏁 Script executed:
Repository: harshshukla2807/echo
Length of output: 798
🏁 Script executed:
Repository: harshshukla2807/echo
Length of output: 91
🌐 Web query:
Convex useMutation API behavior - does it return a promise that needs to be awaited💡 Result:
Yes, the Convex useMutation API returns a promise that should be awaited if you need to handle the result or error. The useMutation hook returns a ReactMutation object, which is callable and returns Promise<FunctionReturnType> when invoked with arguments. Official documentation shows examples using await doSomething and .then/.catch for handling the promise resolution. Example from docs: const doSomething = useMutation(api.functions.doSomething); const onClick = => { const result = await doSomething; // Awaits the promise }; The type definition explicitly states: ReactMutation(...args): Promise<FunctionReturnType>.
Citations:
Await the mutation and add error handling to prevent silent failures and duplicate writes.
Line 15 calls
addUser()without awaiting. SinceuseMutationreturns a promise, the mutation fires asynchronously without error handling or duplicate-click prevention. This means mutation failures are silently ignored, and rapid clicks trigger multiple writes.Add
await, wrap in try/catch, and implement state-based duplicate prevention:Suggested implementation
import { useState } from 'react' import { useMutation, useQuery } from 'convex/react' import { api } from '@workspace/backend/_generated/api' import { Button } from '@workspace/ui/components/button' export default function Page() { const users = useQuery(api.users.getMany) const addUser = useMutation(api.users.add) + const [isAdding, setIsAdding] = useState(false) + const [error, setError] = useState<string | null>(null) + + const handleAddUser = async () => { + if (isAdding) return + setIsAdding(true) + setError(null) + try { + await addUser() + } catch { + setError('Failed to add user. Please retry.') + } finally { + setIsAdding(false) + } + } return ( <div className="flex flex-col items-center justify-center min-h-svh"> - <Button onClick={()=>addUser()}>Add User</Button> + <Button onClick={handleAddUser} disabled={isAdding}> + {isAdding ? 'Adding...' : 'Add User'} + </Button> + {error ? <p role="alert">{error}</p> : null} <p>apps/Web</p>📝 Committable suggestion
🤖 Prompt for AI Agents