Reference

Custom React Hooks

A comprehensive guide to the custom React hooks used in NotebookLLM for managing state and side effects.

Overview

NotebookLLM provides several custom React hooks that encapsulate complex state management and API interactions. These hooks follow React best practices and integrate seamlessly with the application's data fetching patterns.

useNotes

Manages notes within a notebook, providing CRUD operations and auto-save functionality with debouncing.

Usage

const { 
  notes, 
  loading, 
  error, 
  currentNote, 
  isSaving,
  createNote, 
  updateNote, 
  deleteNote,
  selectNote,
  scheduleAutoSave,
  cancelAutoSave 
} = useNotes({ notebookId, autoSaveDelay?: number })

Parameters

PropertyTypeDescription
notebookIdstringThe ID of the notebook to load notes from
autoSaveDelaynumberDelay in ms before auto-saving (default: 1000)

Returns

PropertyDescription
notesArray of notes in the notebook
currentNoteCurrently selected note or null
loadingBoolean indicating if notes are being loaded
errorError message if operation failed
isSavingBoolean indicating if auto-save is in progress
lastSavedDate of last successful save

Example

import { useNotes } from "@/hooks/use-notes"

function NotesEditor({ notebookId }: { notebookId: string }) {
  const { 
    notes, 
    currentNote, 
    loading, 
    createNote, 
    updateNote, 
    selectNote 
  } = useNotes({ notebookId })

  const handleSave = async (content: string) => {
    if (currentNote) {
      await updateNote(currentNote.id, { content })
    }
  }

  const handleAutoSave = (content: string) => {
    if (currentNote) {
      scheduleAutoSave(currentNote.id, { content })
    }
  }

  if (loading) return <div>Loading notes...</div>

  return (
    <div>
      {notes.map(note => (
        <NoteCard 
          key={note.id} 
          note={note} 
          onClick={() => selectNote(note.id)} 
        />
      ))}
      <button onClick={() => createNote({ title: "New Note" })}>
        Add Note
      </button>
    </div>
  )
}

useStudio

Manages content generation in the Studio panel, including podcasts, quizzes, flashcards, and mind maps. Handles async content generation with polling for task status updates.

Usage

const { 
  items, 
  loading, 
  error, 
  generatingTool,
  generateContent, 
  deleteContent,
  refresh 
} = useStudio({ notebookId, pollInterval?: number })

Supported Content Types

  • Audio / Audio Overview - Generate audio
  • podcast-styleQuiz - Generate quiz questions
  • Flashcards - Generate flashcard decks
  • Mind Map - Generate visual mind maps

StudioItem Type

interface StudioItem {
  id: string
  title: string
  sourceCount: number
  timeAgo: string
  type: "quiz" | "audio" | "flashcards" | "mindmap" | "report" | "note"
  status: "pending" | "processing" | "completed" | "failed"
  isNew: boolean
  hasInteractive?: boolean
  content?: Record<string, unknown>
  audioUrl?: string | null
}

Example

import { useStudio } from "@/hooks/use-studio"

function StudioPanel({ notebookId }: { notebookId: string }) {
  const { items, generatingTool, generateContent, deleteContent } = 
    useStudio({ notebookId })

  const handleGenerate = async (tool: string) => {
    await generateContent(tool)
  }

  return (
    <div>
      <div className="generation-buttons">
        <button 
          onClick={() => handleGenerate("Audio")}
          disabled={generatingTool !== null}
        >
          Generate Podcast
        </button>
        <button 
          onClick={() => handleGenerate("Quiz")}
          disabled={generatingTool !== null}
        >
          Generate Quiz
        </button>
      </div>
      
      <div className="content-list">
        {items.map(item => (
          <ContentCard 
            key={item.id} 
            item={item}
            onDelete={() => deleteContent(item.id)}
          />
        ))}
      </div>
    </div>
  )
}

useGoogleDrive

Provides a collection of hooks for integrating with Google Drive, including file browsing, searching, importing, and connection management.

useGoogleDriveStatus

Manages Google Drive connection status and authentication state.

const { status, isLoading, error, refreshStatus } = useGoogleDriveStatus()

useGoogleDriveFiles

Lists files and folders with pagination, navigation, and breadcrumbs support.

const { 
  files, 
  isLoading, 
  error, 
  currentFolder,
  breadcrumbs,
  nextPageToken,
  loadFiles,
  navigateToFolder,
  navigateToRoot,
  navigateUp,
  loadMore
} = useGoogleDriveFiles()

useGoogleDriveSearch

Provides file search functionality with pagination support.

const { 
  results, 
  isSearching, 
  searchQuery,
  search,
  searchMore,
  clearSearch
} = useGoogleDriveSearch()

useGoogleDriveImport

Handles file import from Google Drive to notebooks with progress tracking.

const { 
  importProgress,
  isImporting,
  importFile,
  importMultipleFiles,
  clearImportProgress
} = useGoogleDriveImport(notebookId, onImportComplete?)

useGoogleDriveDisconnect

Provides disconnect functionality for Google Drive integration.

const { disconnect, isDisconnecting } = useGoogleDriveDisconnect()

Example

import { 
  useGoogleDriveStatus, 
  useGoogleDriveFiles,
  useGoogleDriveImport 
} from "@/hooks/use-google-drive"

function GoogleDriveBrowser({ notebookId }: { notebookId: string }) {
  const { status, refreshStatus } = useGoogleDriveStatus()
  const { files, navigateToFolder, loadFiles } = useGoogleDriveFiles()
  const { importFile, importProgress } = useGoogleDriveImport(notebookId)

  useEffect(() => {
    if (status?.connected) {
      loadFiles()
    }
  }, [status?.connected])

  if (!status?.connected) {
    return <ConnectButton onConnect={refreshStatus} />
  }

  return (
    <div>
      <FileList 
        files={files} 
        onFolderClick={navigateToFolder}
      />
      <ImportProgress progress={importProgress} />
    </div>
  )
}

useSuggestedQuestions

Fetches AI-generated suggested questions based on document content or conversation context. Supports both document-based and conversation-based question suggestions.

Usage

const { 
  questions,
  conversationQuestions,
  isLoading,
  isLoadingConversation,
  error,
  documentCount,
  refresh,
  refreshFromConversation
} = useSuggestedQuestions(notebookId)

Two Modes

Document-Based

Initial questions generated from notebook content on mount. Uses the notebook's documents to create relevant study questions.

Conversation-Based (Option B)

Dynamic questions generated after each chat response based on the conversation context.

Example

import { useSuggestedQuestions } from "@/hooks/use-suggested-questions"

function QuestionSuggestions({ notebookId }: { notebookId: string }) {
  const { 
    questions, 
    conversationQuestions,
    isLoading, 
    refresh 
  } = useSuggestedQuestions(notebookId)

  // Use document-based or conversation-based questions
  const displayQuestions = conversationQuestions.length > 0 
    ? conversationQuestions 
    : questions.map(q => q.text)

  return (
    <div>
      <h3>Suggested Questions</h3>
      {isLoading ? (
        <Spinner />
      ) : (
        <ul>
          {displayQuestions.map((question, index) => (
            <li key={index}>
              <button onClick={() => askQuestion(question)}>
                {question}
              </button>
            </li>
          ))}
        </ul>
      )}
      <button onClick={refresh}>Refresh Suggestions</button>
    </div>
  )
}

useScrollReveal

A hook for implementing scroll-based reveal animations using Framer Motion. Triggers animations when elements enter the viewport.

Usage

const { 
  ref, 
  isVisible, 
  animationProps 
} = useScrollReveal(options?)

Options

PropertyDescription
thresholdPercentage of element visible before triggering (0-1)
onceWhether to trigger only once (default: true)
marginMargin from viewport edges

Best Practices

Error Handling

Always handle loading and error states in your components. The hooks provideloading and error properties for this purpose.

Memoization

The hooks use useCallback and useMemo internally to prevent unnecessary re-renders. Avoid wrapping hook functions in your own memoization unless necessary.

Cleanup

Hooks like useNotes handle cleanup automatically (e.g., clearing auto-save timers). The cleanup runs on component unmount.