Skip to main content

getNotes

Retrieve the note for a specific chapter and user.
chapterId
string
required
The unique identifier of the Bible chapter
userId
string
required
The unique identifier of the user whose note to retrieve
note
object | null
The note object for the chapter, or null if no note exists
This function returns only the first note matching the chapter and user. Each user can have one note per chapter.
import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

function ChapterNote({ chapterId }: { chapterId: string }) {
  const note = useQuery(api.notes.getNotes, {
    chapterId,
    userId: "user_123"
  });

  if (!note) {
    return <div>No note for this chapter yet.</div>;
  }

  return (
    <div>
      <h3>My Notes</h3>
      <p>{note.content}</p>
    </div>
  );
}

createNote

Create a new note for a Bible chapter.
chapterId
string
required
The unique identifier of the Bible chapter
content
string
required
The text content of the note
userId
string
required
The unique identifier of the user creating the note
noteId
Id<'notes'>
The unique identifier of the newly created note
import { useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";
import { useState } from "react";

function CreateNote({ chapterId }: { chapterId: string }) {
  const [content, setContent] = useState("");
  const createNote = useMutation(api.notes.createNote);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const noteId = await createNote({
      chapterId,
      content,
      userId: "user_123"
    });
    console.log("Created note:", noteId);
    setContent("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <textarea
        value={content}
        onChange={(e) => setContent(e.target.value)}
        placeholder="Write your notes about this chapter..."
        rows={4}
      />
      <button type="submit">Save Note</button>
    </form>
  );
}

updateNote

Update an existing note’s content.
id
Id<'notes'>
required
The unique identifier of the note to update
content
string
required
The new text content for the note
userId
string
required
The user ID requesting the update to verify ownership
response
null
Returns null on successful update
This function validates that the requesting user owns the note before allowing the update.
import { useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
import { useState } from "react";

function EditNote({ 
  noteId, 
  initialContent 
}: { 
  noteId: Id<"notes">;
  initialContent: string;
}) {
  const [content, setContent] = useState(initialContent);
  const updateNote = useMutation(api.notes.updateNote);
  const [saving, setSaving] = useState(false);

  const handleUpdate = async () => {
    setSaving(true);
    try {
      await updateNote({
        id: noteId,
        content,
        userId: "user_123"
      });
    } finally {
      setSaving(false);
    }
  };

  return (
    <div>
      <textarea
        value={content}
        onChange={(e) => setContent(e.target.value)}
        rows={4}
      />
      <button onClick={handleUpdate} disabled={saving}>
        {saving ? "Saving..." : "Update Note"}
      </button>
    </div>
  );
}
Consider implementing auto-save functionality with debouncing to improve user experience when editing notes.