Viet Tran a38d04c3d5
feat(search): overhaul relevance and curated design data
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.
2026-08-14 00:08:23 +07:00

19 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URLApplies ToStatusVerified At
21StateUse useState for local stateSimple component state should use useState hook in current React apps.useState for form inputs toggles countersClass components this.stateconst [count, setCount] = useState(0)this.state = { count: 0 }Mediumhttps://react.dev/reference/react/useStatereact 19.2.xactive2026-08-13
32StateLift state up when neededShare state between siblings by lifting to parentLift shared state to common ancestorProp drilling through many levelsParent holds state passes downDeep prop chainsMediumhttps://react.dev/learn/sharing-state-between-componentsreact 19.2.xactive2026-08-13
43StateUse useReducer for complex stateComplex state logic benefits from reducer patternuseReducer for state with multiple sub-valuesMultiple useState for related valuesuseReducer with action types5+ useState calls that update togetherMediumhttps://react.dev/reference/react/useReducerreact 19.2.xactive2026-08-13
54StateAvoid unnecessary stateDerive values from existing state when possibleCompute derived values in renderStore derivable values in stateconst total = items.reduce(...)const [total, setTotal] = useState(0)Highhttps://react.dev/learn/choosing-the-state-structurereact 19.2.xactive2026-08-13
65StateInitialize state lazilyUse function form for expensive initial stateuseState(() => computeExpensive())useState(computeExpensive())useState(() => JSON.parse(data))useState(JSON.parse(data))Mediumhttps://react.dev/reference/react/useState#avoiding-recreating-the-initial-statereact 19.2.xactive2026-08-13
76EffectsClean up effectsReturn cleanup for subscriptions and timers so effects stay predictable.Return cleanup function in useEffectNo cleanup for subscriptionsuseEffect(() => { sub(); return unsub; })useEffect(() => { subscribe(); })Highhttps://react.dev/reference/react/useEffect#connecting-to-an-external-systemreact 19.2.xactive2026-08-13
87EffectsSpecify dependencies correctlyInclude every reactive value used inside an Effect dependency array.All referenced values in dependency arrayEmpty deps with external references[value] when using value in effect[] when using props/state in effectHighhttps://react.dev/reference/react/useEffect#specifying-reactive-dependenciesreact 19.2.xactive2026-08-13
98EffectsAvoid unnecessary effectsAvoid Effects for derived data or event handling.Transform data during render handle events directlyuseEffect for derived state or event handlingconst filtered = items.filter(...)useEffect(() => setFiltered(items.filter(...)))Highhttps://react.dev/learn/you-might-not-need-an-effectreact 19.2.xactive2026-08-13
109EffectsUse refs for non-reactive valuesStore values that don't trigger re-renders in refsuseRef for interval IDs DOM elementsuseState for values that don't need renderconst intervalRef = useRef(null)const [intervalId, setIntervalId] = useState()Mediumhttps://react.dev/reference/react/useRefreact 19.2.xactive2026-08-13
1110RenderingUse keys properlyStable unique keys for list itemsUse stable IDs as keysArray index as key for dynamic listskey={item.id}key={index}Highhttps://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-keyreact 19.2.xactive2026-08-13
1211RenderingMemoize expensive calculationsPrefer compiler-first memoization; use useMemo only for measured hotspots or explicit cache boundaries.Use useMemo for expensive computations when profiling shows a real bottleneckUse useMemo everywhere by defaultuseMemo(() => expensive(), [deps])const result = expensiveCalc()Mediumhttps://react.dev/reference/react/useMemoreact 19.2.xactive2026-08-13
1312RenderingMemoize callbacks passed to childrenUse useCallback only when callback identity matters for measured child renders.Use useCallback for handlers passed to memoized children when identity is a bottleneckWrap every function in useCallback by defaultuseCallback(() => {}, [deps])const handler = () => {}Mediumhttps://react.dev/reference/react/useCallbackreact 19.2.xactive2026-08-13
1413RenderingUse React.memo wiselyKeep React.memo as a measured optimization, not a blanket default.Use React.memo for pure components with stable props and real render costMemoize every component or use it as a guessmemo(ExpensiveList)memo(SimpleButton)Lowhttps://react.dev/reference/react/memoreact 19.2.xactive2026-08-13
1514RenderingAvoid inline object/array creation in JSXCreate objects outside render or memoizeDefine style objects outside componentInline objects in props<div style={styles.container}><div style={{ margin: 10 }}>Mediumreact 19.2.xactive2026-08-13
1615ComponentsKeep components small and focusedSingle responsibility for each componentOne concern per componentLarge multi-purpose components<UserAvatar /><UserName /><UserCard /> with 500 linesMediumreact 19.2.xactive2026-08-13
1716ComponentsUse composition over inheritanceCompose components using children and propsUse children prop for flexibilityInheritance hierarchies<Card>{content}</Card>class SpecialCard extends CardMediumhttps://react.dev/learn/thinking-in-reactreact 19.2.xactive2026-08-13
1817ComponentsColocate related codeKeep related components and hooks togetherRelated files in same directoryFlat structure with many filescomponents/User/UserCard.tsxcomponents/UserCard.tsx + hooks/useUser.tsLowreact 19.2.xactive2026-08-13
1918ComponentsUse fragments to avoid extra DOMFragment or <> for multiple elements without wrapper<> for grouping without DOM nodeExtra div wrappers<>{items.map(...)}</><div>{items.map(...)}</div>Lowhttps://react.dev/reference/react/Fragmentreact 19.2.xactive2026-08-13
2019PropsDestructure propsDestructure props for cleaner component codeDestructure in function signatureprops.name props.value throughoutfunction User({ name, age })function User(props)Lowreact 19.2.xactive2026-08-13
2120PropsProvide default props valuesUse default parameters or defaultPropsDefault values in destructuringUndefined checks throughoutfunction Button({ size = 'md' })if (size === undefined) size = 'md'Lowreact 19.2.xactive2026-08-13
2221PropsAvoid prop drillingUse context or composition for deeply nested dataContext for global data composition for UIPassing props through 5+ levels<UserContext.Provider><A user={u}><B user={u}><C user={u}>Mediumhttps://react.dev/learn/passing-data-deeply-with-contextreact 19.2.xactive2026-08-13
2322PropsValidate props with TypeScriptUse TypeScript interfaces for prop typesinterface Props { name: string }PropTypes or no validationinterface ButtonProps { onClick: () => void }Button.propTypes = {}Mediumreact 19.2.xactive2026-08-13
2423EventsUse synthetic events correctlyReact normalizes events across browserse.preventDefault() e.stopPropagation()Access native event unnecessarilyonClick={(e) => e.preventDefault()}onClick={(e) => e.nativeEvent.preventDefault()}Lowhttps://react.dev/reference/react-dom/components/common#react-event-objectreact 19.2.xactive2026-08-13
2524EventsAvoid binding in renderUse arrow functions in class or hooksArrow functions in functional componentsbind in render or constructorconst handleClick = () => {}this.handleClick.bind(this)Mediumreact 19.2.xactive2026-08-13
2625EventsPass event handlers not call resultsPass function reference not invocationonClick={handleClick}onClick={handleClick()} causing immediate callonClick={handleClick}onClick={handleClick()}Highhttps://react.dev/learn/responding-to-eventsreact 19.2.xactive2026-08-13
2726FormsControlled components for formsUse state to control form inputsvalue + onChange for inputsUncontrolled inputs with refs<input value={val} onChange={setVal}><input ref={inputRef}>Mediumhttps://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variablereact 19.2.xactive2026-08-13
2827FormsHandle form submission properlyPrevent default and handle in submit handleronSubmit with preventDefaultonClick on submit button only<form onSubmit={handleSubmit}><button onClick={handleSubmit}>Mediumreact 19.2.xactive2026-08-13
2928FormsDebounce rapid input changesDebounce search/filter inputsuseDeferredValue or debounce for searchFilter on every keystrokeuseDeferredValue(searchTerm)useEffect filtering on every changeMediumhttps://react.dev/reference/react/useDeferredValuereact 19.2.xactive2026-08-13
3029HooksFollow rules of hooksOnly call hooks at the top level of React components or custom hooks.Hooks at component top levelHooks in conditions loops or callbacksconst [x, setX] = useState()if (cond) { const [x, setX] = useState() }Highhttps://react.dev/reference/rules/rules-of-hooksreact 19.2.xactive2026-08-13
3130HooksCustom hooks for reusable logicExtract shared stateful logic to custom hooksuseCustomHook for reusable patternsDuplicate hook logic across componentsconst { data } = useFetch(url)Duplicate useEffect/useState in componentsMediumhttps://react.dev/learn/reusing-logic-with-custom-hooksreact 19.2.xactive2026-08-13
3231HooksName custom hooks with use prefixCustom hooks must start with useuseFetch useForm useAuthfetchData or getData for hookfunction useFetch(url)function fetchData(url)Highhttps://react.dev/learn/reusing-logic-with-custom-hooksreact 19.2.xactive2026-08-13
3332ContextUse context for global dataContext for theme auth localeContext for app-wide stateContext for frequently changing data<ThemeContext.Provider>Context for form field valuesMediumhttps://react.dev/learn/passing-data-deeply-with-contextreact 19.2.xactive2026-08-13
3433ContextSplit contexts by concernSeparate contexts for different domainsThemeContext + AuthContextOne giant AppContext<ThemeProvider><AuthProvider><AppProvider value={{theme user...}}>Mediumreact 19.2.xactive2026-08-13
3534ContextMemoize context valuesPrevent unnecessary re-renders with useMemouseMemo for context value objectNew object reference every rendervalue={useMemo(() => ({...}), [])}value={{ user, theme }}Highhttps://react.dev/reference/react/useMemoreact 19.2.xactive2026-08-13
3635PerformanceUse React DevTools ProfilerProfile to identify performance bottlenecksProfile before optimizingOptimize without measuringReact DevTools ProfilerGuessing at bottlenecksMediumhttps://react.dev/learn/react-developer-toolsreact 19.2.xactive2026-08-13
3736PerformanceLazy load componentsUse React.lazy for code splittinglazy() for routes and heavy componentsImport everything upfrontconst Page = lazy(() => import('./Page'))import Page from './Page'Mediumhttps://react.dev/reference/react/lazyreact 19.2.xactive2026-08-13
3837PerformanceVirtualize long listsUse windowing for lists over 100 itemsreact-window or react-virtualRender thousands of DOM nodes<VirtualizedList items={items}/>{items.map(i => <Item />)}Highhttps://react.dev/learn/rendering-listsreact 19.2.xactive2026-08-13
3938PerformanceBatch state updatesflushSync is a rare escape hatch for synchronous DOM reads/writes.Let React batch related updates; use flushSync only when synchronous DOM work is requiredUse flushSync as a normal batching toolsetA(1); setB(2); // batchedflushSync(() => setA(1))Lowhttps://react.dev/learn/queueing-a-series-of-state-updatesreact 19.2.xactive2026-08-13
4039ErrorHandlingUse error boundariesCatch JavaScript errors in component treeErrorBoundary wrapping sectionsLet errors crash entire app<ErrorBoundary><App/></ErrorBoundary>No error handlingHighhttps://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundaryreact 19.2.xactive2026-08-13
4140ErrorHandlingHandle async errorsCatch errors in async operations and surface failuresHandle or report caught errorsUnhandled or silently swallowed promise rejectionstry { await save() } catch (error) { setError(error) }await save() // no catchHighhttps://react.dev/reference/react/useEffectreact 19.2.xactive2026-08-13
4241TestingTest behavior not implementationTest what user sees and doesTest renders and interactionsTest internal state or methodsexpect(screen.getByText('Hello'))expect(component.state.name)Mediumhttps://testing-library.com/docs/react-testing-library/intro/react 19.2.xactive2026-08-13
4342TestingUse testing-library queriesUse accessible queriesgetByRole getByLabelTextgetByTestId for everythinggetByRole('button')getByTestId('submit-btn')Mediumhttps://testing-library.com/docs/queries/about#priorityreact 19.2.xactive2026-08-13
4443AccessibilityUse semantic HTMLUse semantic HTML elements for their intended behavior.button for clicks nav for navigationdiv with onClick for buttons<button onClick={...}><div onClick={...}>Highhttps://react.dev/reference/react-dom/components#all-html-componentsreact 19.2.xactive2026-08-13
4544AccessibilityManage focus properlyHandle focus for modals dialogsFocus trap in modals return focus on closeNo focus managementuseEffect to focus inputModal without focus trapHighhttps://react.dev/reference/react/useRefreact 19.2.xactive2026-08-13
4645AccessibilityAnnounce dynamic contentUse ARIA live regions for updatesaria-live for dynamic updatesSilent updates to screen readers<div aria-live="polite">{msg}</div><div>{msg}</div>Mediumreact 19.2.xactive2026-08-13
4746AccessibilityLabel form controlsAssociate labels with inputshtmlFor matching input idPlaceholder as only label<label htmlFor="email">Email</label><input placeholder="Email"/>Highhttps://react.dev/reference/react-dom/components/inputreact 19.2.xactive2026-08-13
4847TypeScriptType component propsDefine interfaces for all propsinterface Props with all prop typesany or missing typesinterface Props { name: string }function Component(props: any)Highhttps://react.dev/learn/passing-props-to-a-componentreact 19.2.xactive2026-08-13
4948TypeScriptType state properlyProvide types for useStateuseState<Type>() for complex stateInferred any typesuseState<User | null>(null)useState(null)Mediumreact 19.2.xactive2026-08-13
5049TypeScriptType event handlersUse React event typesReact.ChangeEvent<HTMLInputElement>Generic Event typeonChange: React.ChangeEvent<HTMLInputElement>onChange: EventMediumreact 19.2.xactive2026-08-13
5150TypeScriptUse generics for reusable componentsGeneric components for flexible typingGeneric props for list componentsUnion types for flexibility<List<T> items={T[]}><List items={any[]}>Mediumreact 19.2.xactive2026-08-13
5251PatternsContainer/Presentational splitSeparate data logic from UIContainer fetches presentational rendersMixed data and UI in one<UserContainer><UserView/></UserContainer><User /> with fetch and renderLowreact 19.2.xactive2026-08-13
5352PatternsRender props for flexibilityShare code via render prop patternRender prop for customizable renderingDuplicate logic across components<DataFetcher render={data => ...}/>Copy paste fetch logicLowhttps://react.dev/reference/react/cloneElement#passing-data-with-a-render-propreact 19.2.xactive2026-08-13
5453PatternsCompound componentsRelated components sharing stateTab + TabPanel sharing contextProp drilling between related<Tabs><Tab/><TabPanel/></Tabs><Tabs tabs={[]} panels={[...]}/>Lowreact 19.2.xactive2026-08-13
5554PerformanceUse React Compiler first for memoizationReact 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 helpsTreat useMemo, useCallback, or React.memo as the default first answercompiler-backed build plus measured useMemo or useCallback only when neededblanket manual memoization everywhereHighhttps://react.dev/blog/2025/10/07/react-compiler-1react 19.2.xactive2026-08-13
5655ToolingUse eslint-plugin-react-hooks recommended presetReact Compiler lint rules now ship through eslint-plugin-react-hooks recommended presets.Use the recommended hooks preset with compiler-aware lintingPin older compiler-lint packages as the primary workflowreactHooks.configs.flat.recommendedeslint-plugin-react-compiler as the main lint pathMediumhttps://react.dev/blog/2025/10/07/react-compiler-1react 19.2.xactive2026-08-13
5756HooksUse an Effect Event for non-reactive effect logicUse useEffectEvent to separate event-like logic from reactive Effect dependencies.Read latest props and state inside useEffectEvent callbacksUse useEffectEvent to hide missing dependenciesconst onConnected = useEffectEvent(() => showNotification('Connected!', theme))useEffect(() => { log(theme) }, [])Highhttps://react.dev/reference/react/useEffectEventreact 19.2.xactive2026-08-13
5857ConcurrencyUse Actions with async startTransitionReact 19 Actions let async state updates run as one transition and include side effects.Wrap background state updates and async work in startTransitionAssume Actions are only for synchronous state updatesstartTransition(async () => { await save(); setState(next) })await save(); setState(next)Mediumhttps://react.dev/reference/react/startTransitionreact 19.2.xactive2026-08-13
5958ComponentsPass ref as a propReact 19 supports ref as a prop; this is the current path for exposing DOM nodes.Accept ref as a normal prop in new componentsReach for forwardRef in new codefunction Input({ ref, ...props }) { return <input ref={ref} {...props} /> }const Input = forwardRef(function Input(props, ref) { ... })Mediumhttps://react.dev/reference/react/forwardRefreact 19.2.xactive2026-08-13
6059ComponentsAvoid forwardRef in new codeforwardRef is deprecated in React 19 and should be treated as legacy compatibility code.Migrate to ref as a prop for new and touched componentsIntroduce new forwardRef wrapperslegacy wrapper only while migrating older codeforwardRef for all new componentsHighhttps://react.dev/reference/react/forwardRefreact legacydeprecated2026-08-13
6160SecurityRequire React 19.2.1+ for RSC code pathsReact 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 newerShip 19.2.0 or older on any RSC endpointreact@19.2.1+ react-dom@19.2.1+react@19.2.0Criticalhttps://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-componentsreact 19.2.xactive2026-08-13
6261ToolingTreat eslint-plugin-react-compiler as legacyThe React Compiler release recommends eslint-plugin-react-hooks instead of the older compiler-only lint package.Use eslint-plugin-react-hooks recommended presetsStandardize on eslint-plugin-react-compilerplugin:react-hooks/recommendedeslint-plugin-react-compilerMediumhttps://react.dev/blog/2025/10/07/react-compiler-1react legacydeprecated2026-08-13