Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions docs/react-guidelines/async.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,20 @@ function ProjectPage({ projectId }: { projectId: string }) {

## Debouncing and Throttling

Debounce user input that triggers expensive operations. Keep references stable.
Debounce user input that triggers expensive operations.

```typescript
function useSearchTasks() {
const dispatch = useAppDispatch()
const [query, setQuery] = useState('')

const debouncedSearch = useMemo(
() => debounce((value: string) => dispatch(searchTasks(value)), 300),
[dispatch],
)
const debouncedSearch = debounce((value: string) => dispatch(searchTasks(value)), 300)

const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value
setQuery(value)
debouncedSearch(value)
},
[debouncedSearch],
)
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
const value = event.target.value
setQuery(value)
debouncedSearch(value)
}

// Clean up on unmount
useEffect(
Expand Down
4 changes: 3 additions & 1 deletion docs/react-guidelines/react-compiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ When React Compiler is enabled, **do not** use `useMemo`, `useCallback`, or `Rea

If you find existing `useMemo` or `useCallback` calls in compiler-enabled code, they can be safely removed. See the [Mismatched useMemo dependencies](#mismatched-usememo-dependencies) fix pattern for guidance on handling existing manual memoization that the compiler flags.

> **Warning:** Do **not** remove manual memoization if the component still has compiler violations (check `.react-compiler.rec.json`) or if the compiler is not enabled in the project. In those cases the compiler is not optimizing the component, and removing `useMemo`/`useCallback` would lose memoization entirely.

## Workflow: Identifying and fixing violations

When working on React components or hooks in this codebase, follow this workflow:
Expand Down Expand Up @@ -1107,7 +1109,7 @@ expect(renderCount).toBe(1)
**After:**

```typescript
const onRender = jest.fn()
const onRender = jest.fn() // or vi.fn() in Vitest
function TestComponent() {
return <div />
}
Expand Down
5 changes: 3 additions & 2 deletions docs/react-guidelines/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ Never export the store directly. Only export custom hooks. Consider using the `d

```typescript
import { create } from 'zustand'
import { devtools, immer } from 'zustand/middleware'
import { devtools } from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'

// Store is private
const useFilterStore = create((set) => ({
Expand Down Expand Up @@ -173,7 +174,7 @@ actions: {
export function useFilteredTasks() {
const query = useFilterQuery() // Zustand
const tasks = useAppSelector(selectAllTasks) // Redux
return useMemo(() => tasks.filter((t) => t.content.includes(query)), [tasks, query])
return tasks.filter((t) => t.content.includes(query))
}

// Zustand + Router
Expand Down
2 changes: 1 addition & 1 deletion docs/react-guidelines/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Use React Testing Library with `userEvent` for interactions. Query by role, not test ID.

```typescript
import { screen } from '@testing-library/react'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

test('completes a task when checkbox is clicked', async () => {
Expand Down