Back to all reviewers

Follow hooks rules

supabase/supabase
Based on 4 comments
TSX

Adhere strictly to React hooks rules and best practices to ensure your components behave correctly and predictably. Common issues include: 1. **Manage dependencies properly**: Always include all dependencies in useEffect/useCallback dependency arrays or use useLatest() for values you intentionally exclude to prevent stale data issues.

React TSX

Reviewer Prompt

Adhere strictly to React hooks rules and best practices to ensure your components behave correctly and predictably. Common issues include:

  1. Manage dependencies properly: Always include all dependencies in useEffect/useCallback dependency arrays or use useLatest() for values you intentionally exclude to prevent stale data issues.
// INCORRECT: Missing snap.enforceExactCount and error.code in dependencies
useEffect(() => {
  if (isError && snap.enforceExactCount && error.code === 408) {
    // ...
  }
}, [isError]);

// CORRECT: Include all dependencies
useEffect(() => {
  if (isError && snap.enforceExactCount && error.code === 408) {
    // ...
  }
}, [isError, snap.enforceExactCount, error.code]);

// ALTERNATIVE: Use useLatest for values you want to read but not trigger re-runs
const latestSnap = useLatest(snap);
const latestError = useLatest(error);
useEffect(() => {
  if (isError && latestSnap.current.enforceExactCount && latestError.current.code === 408) {
    // ...
  }
}, [isError]);
  1. Never conditionally call hooks: Instead of conditionally calling hooks, use the enabled option or similar patterns.
// INCORRECT: Conditionally calling a hook breaks the rules of hooks
const { hasAcceptedConsent } = IS_PLATFORM ? useConsentToast() : { hasAcceptedConsent: true }

// CORRECT: Use a parameter to conditionally enable the hook's behavior
const { hasAcceptedConsent } = useConsentToast({ enabled: IS_PLATFORM })
  1. Use useCallback for function props: When passing function props to memoized components, wrap them in useCallback to preserve memoization.
// INCORRECT: Inline function breaks memoization on each render
<MemoizedComponent 
  onResults={(props) => snap.updateMessage({ id: message.id, ...props })}
/>

// CORRECT: Preserve memoization with useCallback
const handleResults = useCallback((props) => {
  snap.updateMessage({ id: message.id, ...props })
}, [message.id, snap])

<MemoizedComponent onResults={handleResults} />
  1. Avoid hooks in loops: Never use hooks inside loops, conditions, or nested functions. Extract them to custom hooks if needed.

Remember that hook calls must be at the top level of your component to ensure they’re called in the same order on each render.

4
Comments Analyzed
TSX
Primary Language
React
Category

Source Discussions