Skip to content

[f] VER-261 - Optimize get snippets with labels#250

Merged
quancao-ea merged 1 commit intomainfrom
features/optimize-get-snippets-with-labels
Sep 23, 2025
Merged

[f] VER-261 - Optimize get snippets with labels#250
quancao-ea merged 1 commit intomainfrom
features/optimize-get-snippets-with-labels

Conversation

@quancao-ea
Copy link
Collaborator

@quancao-ea quancao-ea commented Sep 23, 2025

Important

Optimizes snippet and label handling, updates types and constants, and improves environment variable management.

  • Behavior:
    • Optimizes fetchSnippets in snippet.ts by removing unnecessary Number() conversions.
    • Updates AddLabelButton and LabelButton to use upvote_count and upvoted_by_me instead of detailed upvoter info.
    • In AddLabelButton, invalidates snippet queries after label creation.
    • In LabelButton, invalidates snippet queries after upvote toggle.
  • Types:
    • Updates Label interface in snippet.ts to include upvote_count and upvoted_by_me.
  • Constants:
    • Changes PAGE_SIZE in constants/index.ts from 20 to 10.
  • Environment:
    • Removes type assertions for supabaseUrl and supabaseAnonKey in supabase.ts.
    • Adds vite-env.d.ts for Vite environment variable types.

This description was created by Ellipsis for 6f913ac. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected totals in snippet list (pages and snippet counts).
    • Ensured upvote state and counts stay consistent and revert on errors.
  • Refactor

    • Simplified label data and upvote handling for clearer, faster interactions.
    • Added automatic refresh of snippet lists after label and upvote changes.
    • Optimistic updates now provide snappier feedback when adding labels.
  • Chores

    • Updated pagination size to 10 items per page for easier browsing.
    • Added environment variable typings to improve build reliability.

@quancao-ea quancao-ea self-assigned this Sep 23, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 23, 2025

Walkthrough

Updates label data model and components to use upvote_count/upvoted_by_me, adds optimistic updates and React Query cache invalidation. Adjusts snippet API pagination fields, halves PAGE_SIZE, introduces Vite env typings, and simplifies Supabase env usage.

Changes

Cohort / File(s) Summary of edits
Snippet API pagination fields
src/apis/snippet.ts
Return object now uses data.total_pages and data.num_of_snippets directly (no Number casts).
Label interactions and caching
src/components/AddLabelButton.tsx, src/components/LabelButton.tsx
Switch to new Label fields (upvote_count, upvoted_by_me); add React Query useQueryClient; optimistic updates; invalidate ['snippets','list'] queries after mutations; adjust prop onLabelAdded to accept updater function.
Label data model
src/types/snippet.ts
Label interface replaced fields (applied_at, applied_by, created_by, upvoted_by, is_ai_suggested) with upvote_count: number and upvoted_by_me: boolean.
Pagination constant
src/constants/index.ts
PAGE_SIZE changed from 20 to 10.
Env typing and Supabase setup
src/lib/supabase.ts, src/vite-env.d.ts
Remove string assertions on env vars; add Vite env type declarations (ImportMetaEnv, ImportMeta) for VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant B as AddLabelButton
  participant QC as QueryClient
  participant API as Snippet API
  participant S as Server

  U->>B: Click "Add label"
  B->>B: Build newLabel (uses upvote_count/upvoted_by_me)
  B->>B: onLabelAdded(prev => [...prev, newLabel]) (optimistic)
  B->>API: POST add label
  API->>S: Create label
  alt success
    S-->>API: 200 OK
    API-->>B: Success
    B->>QC: invalidateQueries(['snippets','list', ...])
  else error
    S-->>API: Error
    API-->>B: Error
    B->>B: Revert optimistic label via updater
  end
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant L as LabelButton
  participant QC as QueryClient
  participant API as Snippet API
  participant S as Server

  U->>L: Toggle upvote
  L->>L: Optimistic isUpvoted/upvoteCount update
  L->>API: PATCH toggle upvote
  API->>S: Apply upvote change
  alt success
    S-->>API: 200 OK
    API-->>L: Success
    L->>QC: invalidateQueries(['snippets','list', ...])
  else error
    S-->>API: Error
    API-->>L: Error
    L->>L: Revert optimistic state
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • nhphong
  • giahung68
  • nlgthuan

Poem

I nudge a tag with a hop and a grin,
Upvotes tally—let the bytes begin!
Cache takes a stretch, then wakes anew,
Ten at a time, the snippets queue.
With whisker-twitch and careful care,
I ship my labels light as air. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "[f] Optimize get snippets with labels" is concise and accurately reflects the PR's primary intent—improving snippet retrieval when labels are involved (it matches changes to snippet fetching, label shape, and query invalidation). It communicates the main technical focus without file lists or vague terms. The leading "[f]" tag is non-descriptive but does not make the title misleading.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch features/optimize-get-snippets-with-labels

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @quancao-ea, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces several optimizations aimed at improving the performance and maintainability of snippet and label management. Key changes include a more efficient data structure for labels, reducing the overhead associated with tracking upvotes, and integrating react-query cache invalidation to ensure real-time UI updates. Additionally, it refines pagination settings and enhances type safety for environment variables, contributing to a more robust and responsive application.

Highlights

  • Label Data Structure Refactoring: The Label interface has been significantly simplified, replacing detailed fields like applied_at, applied_by, created_by, upvoted_by, and is_ai_suggested with more efficient upvote_count and upvoted_by_me properties. This change streamlines data handling and reduces client-side processing.
  • React Query Cache Invalidation: Implemented useQueryClient in AddLabelButton and LabelButton components to invalidate the 'snippets' query cache after adding new labels or toggling upvotes. This ensures that the UI reflects the most up-to-date label information without manual refreshes.
  • Pagination Size Adjustment: The PAGE_SIZE constant has been reduced from 20 to 10, potentially optimizing the initial load time and improving performance for snippet retrieval.
  • Environment Variable Type Safety: A new declaration file src/vite-env.d.ts was added to provide type definitions for Vite environment variables, enhancing type safety and developer experience when accessing VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to 6f913ac in 1 minute and 26 seconds. Click for details.
  • Reviewed 194 lines of code in 7 files
  • Skipped 0 files when reviewing.
  • Skipped posting 10 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/apis/snippet.ts:63
  • Draft comment:
    Removed explicit Number() conversion for total_pages and total_snippets. Ensure the API returns numbers to avoid type issues.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
2. src/components/AddLabelButton.tsx:11
  • Draft comment:
    Updated onLabelAdded prop to allow functional updates. Verify that all consumers handle the new signature.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to verify that all consumers handle the new signature, which is against the rules. It doesn't provide a specific suggestion or ask for a specific test to be written.
3. src/components/AddLabelButton.tsx:37
  • Draft comment:
    Refactored newLabel object to use upvote_count and upvoted_by_me. Ensure backend and UI are updated for the new label structure.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to ensure that the backend and UI are updated for the new label structure. This falls under the category of asking the author to ensure something is tested or verified, which is against the rules.
4. src/components/AddLabelButton.tsx:60
  • Draft comment:
    Invalidates snippet queries after label creation. Confirm that the predicate correctly targets all necessary query keys.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
5. src/components/LabelButton.tsx:23
  • Draft comment:
    Refactored upvote state initialization to use upvoted_by_me and upvote_count in place of previous upvoted_by array. Ensure consistency with new Label type.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is informative and suggests ensuring consistency with a new Label type, which is not a specific code suggestion or request for a test. It doesn't ask for confirmation of intention or suggest a specific change.
6. src/components/LabelButton.tsx:80
  • Draft comment:
    Invalidates snippet queries post upvote update. Verify the predicate matches all intended snippet list queries.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment asks the PR author to verify if the predicate matches all intended snippet list queries. This falls under asking the author to confirm or verify something, which is against the rules. Therefore, this comment should be removed.
7. src/constants/index.ts:6
  • Draft comment:
    PAGE_SIZE changed from 20 to 10. Confirm that this reduction in page size is intentional and its implications on pagination are acceptable.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment directly violates one of the key rules: "Do NOT ask the PR author to confirm their intention". The comment is asking for confirmation and to check implications. We should assume the author knows what they're doing when making such a straightforward constant change. Maybe changing page size could have serious performance or UX implications that need to be discussed? While page size changes can have implications, asking for confirmation violates our rules. If there were specific, concrete issues, those should be raised instead. Delete this comment as it merely asks for confirmation of an intentional change without raising any specific issues.
8. src/lib/supabase.ts:3
  • Draft comment:
    Removed explicit string casting for VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY. Ensure these environment variables are always defined to avoid runtime errors.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
9. src/types/snippet.ts:24
  • Draft comment:
    Label interface has been refactored to include upvote_count and upvoted_by_me, removing several audit fields. Ensure all consumers are updated accordingly.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to ensure that all consumers are updated accordingly, which violates the rule against asking the author to ensure compatibility or review dependent parts. It does not provide a specific suggestion or ask for a specific test to be written.
10. src/vite-env.d.ts:1
  • Draft comment:
    vite-env.d.ts setup appears standard; no issues detected.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_NZQuaJZdafHuZ0Aj

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively optimizes snippet and label handling by simplifying the Label data structure, which reduces the data payload. The changes are well-implemented across the components, including updating AddLabelButton and LabelButton to use the new types and to correctly invalidate React Query caches, ensuring data consistency. The removal of unnecessary type conversions and the introduction of typed environment variables are also great improvements for code quality and robustness. Overall, this is a solid set of changes. I have one minor suggestion to improve the typing for a prop to make it more idiomatic.

interface AddLabelButtonProps {
snippetId: string
onLabelAdded: (newLabels: Label[]) => void
onLabelAdded: (newLabels: Label[] | ((prevLabels: Label[]) => Label[])) => void

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better clarity and to follow React idioms, it's recommended to use the React.Dispatch<React.SetStateAction<T>> type for props that are state setters from useState. This makes the prop's purpose as a state dispatcher function immediately clear to other developers.

Suggested change
onLabelAdded: (newLabels: Label[] | ((prevLabels: Label[]) => Label[])) => void
onLabelAdded: React.Dispatch<React.SetStateAction<Label[]>>

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/AddLabelButton.tsx (1)

74-81: Possible crash when allLabels is undefined.

useLabels() may be loading; calling allLabels.filter will throw.

-      const filteredSuggestions = allLabels
+      const source = allLabels ?? []
+      const filteredSuggestions = source
         .filter(label => label.toLowerCase().includes(value.toLowerCase()))
         .slice(0, 10)
🧹 Nitpick comments (8)
src/apis/snippet.ts (1)

1-1: Fix header comment path.

Update to reflect actual file path.

-// src/api/api.ts
+// src/apis/snippet.ts
src/lib/supabase.ts (1)

3-4: Add runtime guards for missing env to fail fast.

Typed envs can still be empty strings; throw a clear error early.

 const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
 const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
+
+if (!supabaseUrl || !supabaseAnonKey) {
+  const missing = [
+    !supabaseUrl && 'VITE_SUPABASE_URL',
+    !supabaseAnonKey && 'VITE_SUPABASE_ANON_KEY'
+  ].filter(Boolean).join(', ')
+  throw new Error(`Missing required env: ${missing}`)
+}

Optionally wire Database types if available for stronger typing.

src/components/AddLabelButton.tsx (4)

36-42: Safer optimistic id generation.

Prefer crypto.randomUUID() with Date.now() fallback to reduce collision risk.

-      id: Date.now().toString(),
+      id: (typeof crypto !== 'undefined' && 'randomUUID' in crypto)
+        ? crypto.randomUUID()
+        : Date.now().toString(),

60-63: Use queryKey-based invalidation for stability.

Predicate on indexes is brittle. Prefer queryKey form (v4/v5 support).

-      queryClient.invalidateQueries({
-        predicate: (query) => query.queryKey[0] === 'snippets' && query.queryKey[1] === 'list'
-      })
+      queryClient.invalidateQueries({ queryKey: ['snippets', 'list'] })

If on v3, keep predicate; if on v4/v5, the above is preferred.


88-91: Guard empty input and trim.

Prevents blank/whitespace labels.

-    if (e.key === 'Enter') {
-      createLabel(inputValue)
+    if (e.key === 'Enter') {
+      const value = inputValue.trim()
+      if (value) createLabel(value)
     }

112-119: Prefer stable keys over array index.

Use suggestion as key since values are unique strings.

-              {suggestions.map((suggestion, index) => (
+              {suggestions.map((suggestion) => (
                 <li
-                  key={index}
+                  key={suggestion}
src/components/LabelButton.tsx (2)

25-31: Harden defaults to avoid undefined state.

Coalesce to booleans/numbers so UI never renders undefined and math never hits NaN.

Apply this diff:

-    return localUpvoted !== null ? localUpvoted : label.upvoted_by_me
+    return localUpvoted !== null ? localUpvoted : !!label.upvoted_by_me
@@
-    return localCount !== null ? localCount : label.upvote_count
+    return localCount !== null ? localCount : (label.upvote_count ?? 0)

42-45: Optional: keep count in sync on logout and normalize boolean.

Counts are global; consider always syncing upvoteCount, and show not-upvoted when user logs out.

Apply this diff:

-    if (user) {
-      setIsUpvoted(label.upvoted_by_me)
-      setUpvoteCount(label.upvote_count)
-    }
+    setUpvoteCount(label.upvote_count ?? 0)
+    setIsUpvoted(user ? !!label.upvoted_by_me : false)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4423654 and 6f913ac.

📒 Files selected for processing (7)
  • src/apis/snippet.ts (1 hunks)
  • src/components/AddLabelButton.tsx (4 hunks)
  • src/components/LabelButton.tsx (4 hunks)
  • src/constants/index.ts (1 hunks)
  • src/lib/supabase.ts (1 hunks)
  • src/types/snippet.ts (1 hunks)
  • src/vite-env.d.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/AddLabelButton.tsx (1)
src/types/snippet.ts (1)
  • Label (24-29)
src/components/LabelButton.tsx (1)
src/lib/storage.ts (1)
  • getLocalStorageItem (1-9)
🔇 Additional comments (8)
src/vite-env.d.ts (1)

3-10: Vite env typings — LGTM.

This unblocks safe import.meta.env usage across the app.

src/constants/index.ts (1)

6-6: PAGE_SIZE halved to 10 — confirm downstream assumptions

Matches fetchSnippets default (10). I couldn't verify in the sandbox (ripgrep skipped files); run these locally to find any remaining hardcoded 20s or PAGE_SIZE usages:

rg -n --hidden -S '\bPAGE_SIZE\b' || true
rg -n --hidden -S 'pageSize\s*[:=]\s*20' || true
rg -n --hidden -S '\b(limit|take|first)\s*[:=]\s*20' || true
rg -n --hidden -S '20\s*(items|per\s*page|per_page|per-page)' || true
# fallback if rg unavailable:
git grep -n --heading --line-number -E "PAGE_SIZE|pageSize\s*[:=]\s*20|20\s*(items|per\s*page|per_page|per-page)" || true
src/types/snippet.ts (1)

24-29: Label shape change — verified; no stale references found.
Occurrences only in src/types/snippet.ts, src/components/AddLabelButton.tsx, src/components/LabelButton.tsx.

src/apis/snippet.ts (2)

27-33: Single source of truth for page size

Replace the literal 10 with PAGE_SIZE from '@/constants'.

+import { PAGE_SIZE } from '@/constants'
@@
-export const fetchSnippets = async ({
-  pageParam = 0,
-  pageSize = 10,
+export const fetchSnippets = async ({
+  pageParam = 0,
+  pageSize = PAGE_SIZE,

Also confirm page index (0 vs 1) matches the get_snippets RPC — frontend currently uses 0 (pageParam default 0; initialPageParam: 0).


62-67: Confirm RPC numeric types or coerce with Number()

PaginatedResponse declares total_pages/total_snippets as number but supabase.rpc returns untyped data — if get_snippets can return numeric/decimal columns as strings, coerce before returning (Number(data.total_pages), Number(data.num_of_snippets)).

File: src/apis/snippet.ts (return block)

  return {
    snippets: data.snippets,
    total_pages: data.total_pages,
    currentPage: pageParam,
    total_snippets: data.num_of_snippets
  }
src/components/LabelButton.tsx (3)

6-6: Type import aligns with new Label shape.

Good switch to the normalized fields (upvoted_by_me, upvote_count).


10-10: React Query client usage looks correct.

Import and hook usage are appropriate.

Also applies to: 21-21


80-83: Use queryKey-based invalidation for snippet lists

The predicate can miss queries with different key shapes; target the snippet lists explicitly.

File: src/components/LabelButton.tsx (invalidateQueries call)

Apply this diff:

-      queryClient.invalidateQueries({
-        predicate: (query) => query.queryKey[0] === 'snippets' && query.queryKey[1] === 'list'
-      })
+      queryClient.invalidateQueries({ queryKey: ['snippets', 'list'] })

Confirm all snippet-list queries use the same ['snippets','list'] key shape before merging.

Comment on lines 9 to 12
interface AddLabelButtonProps {
snippetId: string
onLabelAdded: (newLabels: Label[]) => void
onLabelAdded: (newLabels: Label[] | ((prevLabels: Label[]) => Label[])) => void
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Prop signature union may break existing call sites.

Parents typed as (labels: Label[]) => void won’t accept function args under strictFunctionTypes. Either (a) switch to always passing an updater: (updater: (prev: Label[]) => Label[]) => void, or (b) keep old signature and handle optimistic state locally.


🏁 Script executed:

#!/bin/bash
# Locate usages passing onLabelAdded to ensure they handle the union/function form
rg -nP -C2 '<AddLabelButton\b[^>]*onLabelAdded=' --type=tsx

Length of output: 27


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "PWD: $(pwd)"
echo "Checking for src/components/AddLabelButton.tsx..."
if [ -f src/components/AddLabelButton.tsx ]; then
  echo "---- src/components/AddLabelButton.tsx (first 240 lines) ----"
  sed -n '1,240p' src/components/AddLabelButton.tsx || true
else
  echo "File not found: src/components/AddLabelButton.tsx"
fi

echo
echo "Searching repo for 'onLabelAdded' occurrences in ts/tsx/js/jsx files..."
rg -n --hidden --glob '!**/node_modules/**' "onLabelAdded" -g "**/*.{ts,tsx,js,jsx}" -S || true

echo
echo "Searching repo for JSX usage of AddLabelButton..."
rg -n --hidden --glob '!**/node_modules/**' "<AddLabelButton\\b" -g "**/*.{ts,tsx,js,jsx}" -S || true

echo
echo "Searching repo for identifier 'AddLabelButton'..."
rg -n --hidden --glob '!**/node_modules/**' "AddLabelButton" -g "**/*.{ts,tsx,js,jsx}" -S || true

Length of output: 6123


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- src/components/SnippetCard.tsx ----"
sed -n '1,400p' src/components/SnippetCard.tsx || true

echo
echo "---- src/components/SnippetDetail.tsx ----"
sed -n '1,800p' src/components/SnippetDetail.tsx || true

Length of output: 24597


onLabelAdded prop type is incompatible with SnippetCard under strictFunctionTypes

AddLabelButton defines onLabelAdded as (Label[] | ((prev: Label[]) => Label[])) => void, but src/components/SnippetCard.tsx provides handleLabelAdded: (newLabels: Label[]) => void — this is not assignable with strictFunctionTypes and will cause a TypeScript error. src/components/SnippetDetail.tsx already accepts the union.

  • Fix (recommended): make the prop a SetStateAction dispatcher for clarity and compatibility — onLabelAdded: React.Dispatch<React.SetStateAction<Label[]>> — then pass setLabels (or typed handler) from parents (e.g., ).
  • Alternate: update SnippetCard.handleLabelAdded signature to accept Label[] | ((prev: Label[]) => Label[]), or change AddLabelButton to only call updater functions and update types consistently.
    Files: src/components/AddLabelButton.tsx, src/components/SnippetCard.tsx, src/components/SnippetDetail.tsx.
🤖 Prompt for AI Agents
In src/components/AddLabelButton.tsx around lines 9-12, the onLabelAdded prop is
typed as (newLabels: Label[] | ((prevLabels: Label[]) => Label[])) => void which
is incompatible with SnippetCard's (newLabels: Label[]) => void under
strictFunctionTypes; change the prop to a SetStateAction dispatcher:
onLabelAdded: React.Dispatch<React.SetStateAction<Label[]>> and update callers
to pass the state setter (e.g., setLabels) or an appropriately typed wrapper so
AddLabelButton can call it with either a Label[] or an updater function;
alternatively ensure SnippetCard and SnippetDetail use the same dispatcher type
if they currently pass setLabels.

@quancao-ea quancao-ea merged commit 5f114c5 into main Sep 23, 2025
2 checks passed
@quancao-ea quancao-ea changed the title [f] Optimize get snippets with labels [f] VER-261 - Optimize get snippets with labels Sep 23, 2025
@linear
Copy link

linear bot commented Sep 23, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants