mirror of
https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git
synced 2026-08-14 08:49:05 +00:00
Overhaul BM25 relevance, reasoning and data-quality contracts; refresh UI styles and framework guidance; add resilient text, chip, badge and micro-interaction guidance; strengthen release, provenance and catalog refresh gates; update bilingual documentation.
19 KiB
19 KiB
| 1 | No | Category | Guideline | Description | Do | Don't | Code Good | Code Bad | Severity | Docs URL | Applies To | Status | Verified At |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 1 | State | Use useState for local state | Simple component state should use useState hook in current React apps. | useState for form inputs toggles counters | Class components this.state | const [count, setCount] = useState(0) | this.state = { count: 0 } | Medium | https://react.dev/reference/react/useState | react 19.2.x | active | 2026-08-13 |
| 3 | 2 | State | Lift state up when needed | Share state between siblings by lifting to parent | Lift shared state to common ancestor | Prop drilling through many levels | Parent holds state passes down | Deep prop chains | Medium | https://react.dev/learn/sharing-state-between-components | react 19.2.x | active | 2026-08-13 |
| 4 | 3 | State | Use useReducer for complex state | Complex state logic benefits from reducer pattern | useReducer for state with multiple sub-values | Multiple useState for related values | useReducer with action types | 5+ useState calls that update together | Medium | https://react.dev/reference/react/useReducer | react 19.2.x | active | 2026-08-13 |
| 5 | 4 | State | Avoid unnecessary state | Derive values from existing state when possible | Compute derived values in render | Store derivable values in state | const total = items.reduce(...) | const [total, setTotal] = useState(0) | High | https://react.dev/learn/choosing-the-state-structure | react 19.2.x | active | 2026-08-13 |
| 6 | 5 | State | Initialize state lazily | Use function form for expensive initial state | useState(() => computeExpensive()) | useState(computeExpensive()) | useState(() => JSON.parse(data)) | useState(JSON.parse(data)) | Medium | https://react.dev/reference/react/useState#avoiding-recreating-the-initial-state | react 19.2.x | active | 2026-08-13 |
| 7 | 6 | Effects | Clean up effects | Return cleanup for subscriptions and timers so effects stay predictable. | Return cleanup function in useEffect | No cleanup for subscriptions | useEffect(() => { sub(); return unsub; }) | useEffect(() => { subscribe(); }) | High | https://react.dev/reference/react/useEffect#connecting-to-an-external-system | react 19.2.x | active | 2026-08-13 |
| 8 | 7 | Effects | Specify dependencies correctly | Include every reactive value used inside an Effect dependency array. | All referenced values in dependency array | Empty deps with external references | [value] when using value in effect | [] when using props/state in effect | High | https://react.dev/reference/react/useEffect#specifying-reactive-dependencies | react 19.2.x | active | 2026-08-13 |
| 9 | 8 | Effects | Avoid unnecessary effects | Avoid Effects for derived data or event handling. | Transform data during render handle events directly | useEffect for derived state or event handling | const filtered = items.filter(...) | useEffect(() => setFiltered(items.filter(...))) | High | https://react.dev/learn/you-might-not-need-an-effect | react 19.2.x | active | 2026-08-13 |
| 10 | 9 | Effects | Use refs for non-reactive values | Store values that don't trigger re-renders in refs | useRef for interval IDs DOM elements | useState for values that don't need render | const intervalRef = useRef(null) | const [intervalId, setIntervalId] = useState() | Medium | https://react.dev/reference/react/useRef | react 19.2.x | active | 2026-08-13 |
| 11 | 10 | Rendering | Use keys properly | Stable unique keys for list items | Use stable IDs as keys | Array index as key for dynamic lists | key={item.id} | key={index} | High | https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key | react 19.2.x | active | 2026-08-13 |
| 12 | 11 | Rendering | Memoize expensive calculations | Prefer compiler-first memoization; use useMemo only for measured hotspots or explicit cache boundaries. | Use useMemo for expensive computations when profiling shows a real bottleneck | Use useMemo everywhere by default | useMemo(() => expensive(), [deps]) | const result = expensiveCalc() | Medium | https://react.dev/reference/react/useMemo | react 19.2.x | active | 2026-08-13 |
| 13 | 12 | Rendering | Memoize callbacks passed to children | Use useCallback only when callback identity matters for measured child renders. | Use useCallback for handlers passed to memoized children when identity is a bottleneck | Wrap every function in useCallback by default | useCallback(() => {}, [deps]) | const handler = () => {} | Medium | https://react.dev/reference/react/useCallback | react 19.2.x | active | 2026-08-13 |
| 14 | 13 | Rendering | Use React.memo wisely | Keep React.memo as a measured optimization, not a blanket default. | Use React.memo for pure components with stable props and real render cost | Memoize every component or use it as a guess | memo(ExpensiveList) | memo(SimpleButton) | Low | https://react.dev/reference/react/memo | react 19.2.x | active | 2026-08-13 |
| 15 | 14 | Rendering | Avoid inline object/array creation in JSX | Create objects outside render or memoize | Define style objects outside component | Inline objects in props | <div style={styles.container}> | <div style={{ margin: 10 }}> | Medium | react 19.2.x | active | 2026-08-13 | |
| 16 | 15 | Components | Keep components small and focused | Single responsibility for each component | One concern per component | Large multi-purpose components | <UserAvatar /><UserName /> | <UserCard /> with 500 lines | Medium | react 19.2.x | active | 2026-08-13 | |
| 17 | 16 | Components | Use composition over inheritance | Compose components using children and props | Use children prop for flexibility | Inheritance hierarchies | <Card>{content}</Card> | class SpecialCard extends Card | Medium | https://react.dev/learn/thinking-in-react | react 19.2.x | active | 2026-08-13 |
| 18 | 17 | Components | Colocate related code | Keep related components and hooks together | Related files in same directory | Flat structure with many files | components/User/UserCard.tsx | components/UserCard.tsx + hooks/useUser.ts | Low | react 19.2.x | active | 2026-08-13 | |
| 19 | 18 | Components | Use fragments to avoid extra DOM | Fragment or <> for multiple elements without wrapper | <> for grouping without DOM node | Extra div wrappers | <>{items.map(...)}</> | <div>{items.map(...)}</div> | Low | https://react.dev/reference/react/Fragment | react 19.2.x | active | 2026-08-13 |
| 20 | 19 | Props | Destructure props | Destructure props for cleaner component code | Destructure in function signature | props.name props.value throughout | function User({ name, age }) | function User(props) | Low | react 19.2.x | active | 2026-08-13 | |
| 21 | 20 | Props | Provide default props values | Use default parameters or defaultProps | Default values in destructuring | Undefined checks throughout | function Button({ size = 'md' }) | if (size === undefined) size = 'md' | Low | react 19.2.x | active | 2026-08-13 | |
| 22 | 21 | Props | Avoid prop drilling | Use context or composition for deeply nested data | Context for global data composition for UI | Passing props through 5+ levels | <UserContext.Provider> | <A user={u}><B user={u}><C user={u}> | Medium | https://react.dev/learn/passing-data-deeply-with-context | react 19.2.x | active | 2026-08-13 |
| 23 | 22 | Props | Validate props with TypeScript | Use TypeScript interfaces for prop types | interface Props { name: string } | PropTypes or no validation | interface ButtonProps { onClick: () => void } | Button.propTypes = {} | Medium | react 19.2.x | active | 2026-08-13 | |
| 24 | 23 | Events | Use synthetic events correctly | React normalizes events across browsers | e.preventDefault() e.stopPropagation() | Access native event unnecessarily | onClick={(e) => e.preventDefault()} | onClick={(e) => e.nativeEvent.preventDefault()} | Low | https://react.dev/reference/react-dom/components/common#react-event-object | react 19.2.x | active | 2026-08-13 |
| 25 | 24 | Events | Avoid binding in render | Use arrow functions in class or hooks | Arrow functions in functional components | bind in render or constructor | const handleClick = () => {} | this.handleClick.bind(this) | Medium | react 19.2.x | active | 2026-08-13 | |
| 26 | 25 | Events | Pass event handlers not call results | Pass function reference not invocation | onClick={handleClick} | onClick={handleClick()} causing immediate call | onClick={handleClick} | onClick={handleClick()} | High | https://react.dev/learn/responding-to-events | react 19.2.x | active | 2026-08-13 |
| 27 | 26 | Forms | Controlled components for forms | Use state to control form inputs | value + onChange for inputs | Uncontrolled inputs with refs | <input value={val} onChange={setVal}> | <input ref={inputRef}> | Medium | https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable | react 19.2.x | active | 2026-08-13 |
| 28 | 27 | Forms | Handle form submission properly | Prevent default and handle in submit handler | onSubmit with preventDefault | onClick on submit button only | <form onSubmit={handleSubmit}> | <button onClick={handleSubmit}> | Medium | react 19.2.x | active | 2026-08-13 | |
| 29 | 28 | Forms | Debounce rapid input changes | Debounce search/filter inputs | useDeferredValue or debounce for search | Filter on every keystroke | useDeferredValue(searchTerm) | useEffect filtering on every change | Medium | https://react.dev/reference/react/useDeferredValue | react 19.2.x | active | 2026-08-13 |
| 30 | 29 | Hooks | Follow rules of hooks | Only call hooks at the top level of React components or custom hooks. | Hooks at component top level | Hooks in conditions loops or callbacks | const [x, setX] = useState() | if (cond) { const [x, setX] = useState() } | High | https://react.dev/reference/rules/rules-of-hooks | react 19.2.x | active | 2026-08-13 |
| 31 | 30 | Hooks | Custom hooks for reusable logic | Extract shared stateful logic to custom hooks | useCustomHook for reusable patterns | Duplicate hook logic across components | const { data } = useFetch(url) | Duplicate useEffect/useState in components | Medium | https://react.dev/learn/reusing-logic-with-custom-hooks | react 19.2.x | active | 2026-08-13 |
| 32 | 31 | Hooks | Name custom hooks with use prefix | Custom hooks must start with use | useFetch useForm useAuth | fetchData or getData for hook | function useFetch(url) | function fetchData(url) | High | https://react.dev/learn/reusing-logic-with-custom-hooks | react 19.2.x | active | 2026-08-13 |
| 33 | 32 | Context | Use context for global data | Context for theme auth locale | Context for app-wide state | Context for frequently changing data | <ThemeContext.Provider> | Context for form field values | Medium | https://react.dev/learn/passing-data-deeply-with-context | react 19.2.x | active | 2026-08-13 |
| 34 | 33 | Context | Split contexts by concern | Separate contexts for different domains | ThemeContext + AuthContext | One giant AppContext | <ThemeProvider><AuthProvider> | <AppProvider value={{theme user...}}> | Medium | react 19.2.x | active | 2026-08-13 | |
| 35 | 34 | Context | Memoize context values | Prevent unnecessary re-renders with useMemo | useMemo for context value object | New object reference every render | value={useMemo(() => ({...}), [])} | value={{ user, theme }} | High | https://react.dev/reference/react/useMemo | react 19.2.x | active | 2026-08-13 |
| 36 | 35 | Performance | Use React DevTools Profiler | Profile to identify performance bottlenecks | Profile before optimizing | Optimize without measuring | React DevTools Profiler | Guessing at bottlenecks | Medium | https://react.dev/learn/react-developer-tools | react 19.2.x | active | 2026-08-13 |
| 37 | 36 | Performance | Lazy load components | Use React.lazy for code splitting | lazy() for routes and heavy components | Import everything upfront | const Page = lazy(() => import('./Page')) | import Page from './Page' | Medium | https://react.dev/reference/react/lazy | react 19.2.x | active | 2026-08-13 |
| 38 | 37 | Performance | Virtualize long lists | Use windowing for lists over 100 items | react-window or react-virtual | Render thousands of DOM nodes | <VirtualizedList items={items}/> | {items.map(i => <Item />)} | High | https://react.dev/learn/rendering-lists | react 19.2.x | active | 2026-08-13 |
| 39 | 38 | Performance | Batch state updates | flushSync is a rare escape hatch for synchronous DOM reads/writes. | Let React batch related updates; use flushSync only when synchronous DOM work is required | Use flushSync as a normal batching tool | setA(1); setB(2); // batched | flushSync(() => setA(1)) | Low | https://react.dev/learn/queueing-a-series-of-state-updates | react 19.2.x | active | 2026-08-13 |
| 40 | 39 | ErrorHandling | Use error boundaries | Catch JavaScript errors in component tree | ErrorBoundary wrapping sections | Let errors crash entire app | <ErrorBoundary><App/></ErrorBoundary> | No error handling | High | https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary | react 19.2.x | active | 2026-08-13 |
| 41 | 40 | ErrorHandling | Handle async errors | Catch errors in async operations and surface failures | Handle or report caught errors | Unhandled or silently swallowed promise rejections | try { await save() } catch (error) { setError(error) } | await save() // no catch | High | https://react.dev/reference/react/useEffect | react 19.2.x | active | 2026-08-13 |
| 42 | 41 | Testing | Test behavior not implementation | Test what user sees and does | Test renders and interactions | Test internal state or methods | expect(screen.getByText('Hello')) | expect(component.state.name) | Medium | https://testing-library.com/docs/react-testing-library/intro/ | react 19.2.x | active | 2026-08-13 |
| 43 | 42 | Testing | Use testing-library queries | Use accessible queries | getByRole getByLabelText | getByTestId for everything | getByRole('button') | getByTestId('submit-btn') | Medium | https://testing-library.com/docs/queries/about#priority | react 19.2.x | active | 2026-08-13 |
| 44 | 43 | Accessibility | Use semantic HTML | Use semantic HTML elements for their intended behavior. | button for clicks nav for navigation | div with onClick for buttons | <button onClick={...}> | <div onClick={...}> | High | https://react.dev/reference/react-dom/components#all-html-components | react 19.2.x | active | 2026-08-13 |
| 45 | 44 | Accessibility | Manage focus properly | Handle focus for modals dialogs | Focus trap in modals return focus on close | No focus management | useEffect to focus input | Modal without focus trap | High | https://react.dev/reference/react/useRef | react 19.2.x | active | 2026-08-13 |
| 46 | 45 | Accessibility | Announce dynamic content | Use ARIA live regions for updates | aria-live for dynamic updates | Silent updates to screen readers | <div aria-live="polite">{msg}</div> | <div>{msg}</div> | Medium | react 19.2.x | active | 2026-08-13 | |
| 47 | 46 | Accessibility | Label form controls | Associate labels with inputs | htmlFor matching input id | Placeholder as only label | <label htmlFor="email">Email</label> | <input placeholder="Email"/> | High | https://react.dev/reference/react-dom/components/input | react 19.2.x | active | 2026-08-13 |
| 48 | 47 | TypeScript | Type component props | Define interfaces for all props | interface Props with all prop types | any or missing types | interface Props { name: string } | function Component(props: any) | High | https://react.dev/learn/passing-props-to-a-component | react 19.2.x | active | 2026-08-13 |
| 49 | 48 | TypeScript | Type state properly | Provide types for useState | useState<Type>() for complex state | Inferred any types | useState<User | null>(null) | useState(null) | Medium | react 19.2.x | active | 2026-08-13 | |
| 50 | 49 | TypeScript | Type event handlers | Use React event types | React.ChangeEvent<HTMLInputElement> | Generic Event type | onChange: React.ChangeEvent<HTMLInputElement> | onChange: Event | Medium | react 19.2.x | active | 2026-08-13 | |
| 51 | 50 | TypeScript | Use generics for reusable components | Generic components for flexible typing | Generic props for list components | Union types for flexibility | <List<T> items={T[]}> | <List items={any[]}> | Medium | react 19.2.x | active | 2026-08-13 | |
| 52 | 51 | Patterns | Container/Presentational split | Separate data logic from UI | Container fetches presentational renders | Mixed data and UI in one | <UserContainer><UserView/></UserContainer> | <User /> with fetch and render | Low | react 19.2.x | active | 2026-08-13 | |
| 53 | 52 | Patterns | Render props for flexibility | Share code via render prop pattern | Render prop for customizable rendering | Duplicate logic across components | <DataFetcher render={data => ...}/> | Copy paste fetch logic | Low | https://react.dev/reference/react/cloneElement#passing-data-with-a-render-prop | react 19.2.x | active | 2026-08-13 |
| 54 | 53 | Patterns | Compound components | Related components sharing state | Tab + TabPanel sharing context | Prop drilling between related | <Tabs><Tab/><TabPanel/></Tabs> | <Tabs tabs={[]} panels={[...]}/> | Low | react 19.2.x | active | 2026-08-13 | |
| 55 | 54 | Performance | Use React Compiler first for memoization | React Compiler provides automatic memoization; keep manual memoization only for measured hotspots or unsupported cases. | Enable the compiler, then use manual memoization only when profiling proves it helps | Treat useMemo, useCallback, or React.memo as the default first answer | compiler-backed build plus measured useMemo or useCallback only when needed | blanket manual memoization everywhere | High | https://react.dev/blog/2025/10/07/react-compiler-1 | react 19.2.x | active | 2026-08-13 |
| 56 | 55 | Tooling | Use eslint-plugin-react-hooks recommended preset | React Compiler lint rules now ship through eslint-plugin-react-hooks recommended presets. | Use the recommended hooks preset with compiler-aware linting | Pin older compiler-lint packages as the primary workflow | reactHooks.configs.flat.recommended | eslint-plugin-react-compiler as the main lint path | Medium | https://react.dev/blog/2025/10/07/react-compiler-1 | react 19.2.x | active | 2026-08-13 |
| 57 | 56 | Hooks | Use an Effect Event for non-reactive effect logic | Use useEffectEvent to separate event-like logic from reactive Effect dependencies. | Read latest props and state inside useEffectEvent callbacks | Use useEffectEvent to hide missing dependencies | const onConnected = useEffectEvent(() => showNotification('Connected!', theme)) | useEffect(() => { log(theme) }, []) | High | https://react.dev/reference/react/useEffectEvent | react 19.2.x | active | 2026-08-13 |
| 58 | 57 | Concurrency | Use Actions with async startTransition | React 19 Actions let async state updates run as one transition and include side effects. | Wrap background state updates and async work in startTransition | Assume Actions are only for synchronous state updates | startTransition(async () => { await save(); setState(next) }) | await save(); setState(next) | Medium | https://react.dev/reference/react/startTransition | react 19.2.x | active | 2026-08-13 |
| 59 | 58 | Components | Pass ref as a prop | React 19 supports ref as a prop; this is the current path for exposing DOM nodes. | Accept ref as a normal prop in new components | Reach for forwardRef in new code | function Input({ ref, ...props }) { return <input ref={ref} {...props} /> } | const Input = forwardRef(function Input(props, ref) { ... }) | Medium | https://react.dev/reference/react/forwardRef | react 19.2.x | active | 2026-08-13 |
| 60 | 59 | Components | Avoid forwardRef in new code | forwardRef is deprecated in React 19 and should be treated as legacy compatibility code. | Migrate to ref as a prop for new and touched components | Introduce new forwardRef wrappers | legacy wrapper only while migrating older code | forwardRef for all new components | High | https://react.dev/reference/react/forwardRef | react legacy | deprecated | 2026-08-13 |
| 61 | 60 | Security | Require React 19.2.1+ for RSC code paths | React Server Components had an unauthenticated RCE in 19.2.0; treat 19.2.1+ as the security floor. | Pin React RSC stacks to 19.2.1 or newer | Ship 19.2.0 or older on any RSC endpoint | react@19.2.1+ react-dom@19.2.1+ | react@19.2.0 | Critical | https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components | react 19.2.x | active | 2026-08-13 |
| 62 | 61 | Tooling | Treat eslint-plugin-react-compiler as legacy | The React Compiler release recommends eslint-plugin-react-hooks instead of the older compiler-only lint package. | Use eslint-plugin-react-hooks recommended presets | Standardize on eslint-plugin-react-compiler | plugin:react-hooks/recommended | eslint-plugin-react-compiler | Medium | https://react.dev/blog/2025/10/07/react-compiler-1 | react legacy | deprecated | 2026-08-13 |