Loading...
Loading...
Frontend PR checklist for React, Next.js, Vue.js, Tailwind CSS, and React Query (F1–F16). Use when user says "frontend review", "review my React/Vue PR", "check my UI code", working in a frontend repo, or when the diff contains .tsx/.vue/.css files. For the full review workflow, use pr-review.
npx skill4agent add gadanihiman/grs-skills pr-check-frontendpr-review-staticpr-review-humangit diff main...HEAD"Hook called inside a condition — if the condition is false on the first render, hook order changes on subsequent renders and causes state corruption."
useStateuseEffectuseMemouseCallbackuseQueryifforuseEffect"The effect readsbut it's missing from the dependency array — the effect will always run with the initial value even after userId changes." "Adding the callback directly in deps withoutuserIdcauses the effect to re-run on every render."useCallback
useEffectuseCallbackReact.memouseCallbackuseMemostyle={{ margin: 0 }}key"Using array index as key means inserting an item at the top shifts all keys, causing React to re-render every item instead of just inserting one."
.map()keyMath.random()item.id"accessed at module level — throwswindow.localStorageduring SSR." "ReferenceError: window is not definedcalled outside a component — works in browser but fails during static generation."useRouter()
windowdocumentnavigatorlocalStorageuseEffecttypeof window !== 'undefined'window{ ssr: false }useSearchParams()Suspense<img><Image><Image><img><Image>widthheightfillnext.config.jsimages.domainsnext/font<link>_documentstaleTime0errorisLoadingonErrorqueryClient.invalidateQueriesenabled: !!dependencyset()reactive()obj.newProp = valueref.value<script setup>computedwatchv-for:key"will be purged because Tailwind can't statically analyse the full class name."'text-' + color
`text-${color}`condition ? 'text-red-500' : 'text-green-500''text-' + colortailwind.config.jssafelistsm:md:lg:<img>altalt=""<div onClick><span onClick><button><a><label>htmlForforaria-labelaria-labelany?React.ChangeEvent<HTMLInputElement>anychildrenReact.ReactNoderefReact.Ref<ElementType>forwardRefuseStateuseMemocomputeduseStateuseStateNEXT_PUBLIC_VITE_NEXT_PUBLIC_.env.exampleimport _ from 'lodash'import debounce from 'lodash/debounce'dynamic(() => import(...), { ssr: false })error.tsxloading.tsxSuspenseuseState[F3] components/ProductList.tsx:42
Severity: Medium
Issue: Anonymous callback passed as onClick prop to memoized child — defeats memo.
Fix: Wrap the callback in useCallback with appropriate dependencies.
[F9] components/Badge.tsx:8
Severity: High
Issue: Class name constructed as `'bg-' + color` — will be purged in production build.
Fix: Use full class names: condition ? 'bg-red-500' : 'bg-green-500'.