Skip to content
Created: October 4, 2025

1. Status management practical mode ​

1️⃣ Local state vs global state split principle ​

✅ Partial status (priority) ​

  • form
  • Pop-up window switch
  • hover / loading
  • Local UI state

Use:

js
useState
useReducer

Principles:

Keep state as close as possible to the component using it

✅ Global status ​

Don't abuse Context.

Recommended:

  • Lightweight scenario: Context + selector
  • Medium and large projects: zustand/jotai
  • Super complex: redux-toolkit

Advanced optimization points:

  • Cut store (split by domain)
  • selector precise subscription
  • Avoid top-level large objects

2️⃣ useReducer actual combat scenario ​

Suitable for: ​

  • Multi-field linkage form
  • State machine process
  • Complex business logic

Example:

js
const [state, dispatch] = useReducer(reducer, initialState)

Advantages:

  • Centralized status
  • testable
  • Traceable

Interview highlights:

Use useReducer to build a lightweight state machine

2. Best practices for side effect management ​

3️⃣ Request encapsulation: useRequest mode ​

Don't write fetch directly in the component.

Recommended structure: ​

js
function useRequest(service, options) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  const abortRef = useRef(null)

  const run = useCallback(async (...args) => {
    abortRef.current?.abort()
    const controller = new AbortController()
    abortRef.current = controller

    setLoading(true)
    const result = await service(...args, controller.signal)
    setData(result)
    setLoading(false)
  }, [service])

  useEffect(() => {
    return () => abortRef.current?.abort()
  }, [])

  return { data, loading, run }
}

Practical points: ​

  • Support cancellation requests
  • Support repeated calls
  • Prevent memory leaks
  • Ensure reference stability

4️⃣ Streaming output scenario (AI Chat) ​

You are currently preparing the AI Chat architecture, which is very critical.

Core questions:

  • Streaming updates can lead to frequent re-renders
  • Long conversations can get laggy
  • Interruptible if needed

Optimization plan:

  • useRef cache
  • RAF merge update
  • useTransition reduces priority
  • Message layering memo

3. Practical performance optimization ​

5️⃣ Correct use of useMemo / useCallback ​

❌ Common mistakes ​

  • Package useCallback everywhere
  • deps is incorrectly filled in
  • Optimize for optimization's sake

✅ Correct usage scenarios ​

  • Passed to React.memo subcomponent
  • as useEffect dependency
  • big calculation

6️⃣ Large list optimization ​

Scenario: 2000 messages

Practical combination: ​

  • virtual list
  • Message component React.memo
  • key stable
  • State splitting (do not replace messages as a whole)

Error example:

js
setMessages([...messages, newMsg])

Optimization:

  • Use functional updates
  • Split into map + id storage

4. Practical solutions to closure problems ​

7️⃣ Timer Hook package ​

Wrong writing:

js
setInterval(() => console.log(count), 1000)

Correct packaging:

js
function useInterval(callback, delay) {
  const savedCallback = useRef(callback)

  useEffect(() => {
    savedCallback.current = callback
  })

  useEffect(() => {
    const id = setInterval(() => {
      savedCallback.current()
    }, delay)
    return () => clearInterval(id)
  }, [delay])
}

Advantages:

  • Always get the latest state
  • Do not re-register interval

5. Advanced usage of Context ​

8️⃣ Avoid full refresh ​

Question:

Context value changes → All subcomponents are re-rendered

Solution:

  • Split multiple contexts
  • useMemo wraps value
  • selector mode

6. Practical combat of concurrency features ​

9️⃣ useTransition scenario ​

Search filter:

js
const [isPending, startTransition] = useTransition()

const onSearch = (value) => {
  setInput(value)

  startTransition(() => {
    setFilteredList(filter(value))
  })
}

Effect:

  • Input without lag
  • filter low priority

🔟 useDeferredValue scenario ​

Used for:

  • large table
  • Data graph

Differences from useMemo:

  • useMemo is cache
  • useDeferredValue is the scheduling delay

7. Hooks design specifications (team level) ​

1️⃣1️⃣ Custom Hook design principles ​

  • Name useXxx
  • single responsibility
  • Do not expose internal state structures
  • The returned object structure is stable

Recommended:

js
return useMemo(() => ({
  data,
  loading,
  run
}), [data, loading, run])

1️⃣2️⃣ Dependence on array specification ​

Principles:

  • Don't ignore ESLint hints
  • Don't add eslint-disable casually
  • Don't write objects into deps (unless memo)

8. Summary of enterprise-level best practices ​

state design ​

  • state minimized
  • Data normalization
  • Split granularity

side effect design ​

  • All side effects must be treatable
  • Component uninstallation must be considered
  • Request must be cancelable

Performance design ​

  • Not over-optimized by default
  • critical path optimization
  • Verify with profiler

9. Summary of senior front-end interview ​

In React projects, I usually follow the state proximity principle, use useReducer to handle complex logic, use custom Hooks to encapsulate side effects, and combine useTransition to optimize long lists or search scenarios.Have a deep understanding of closure issues and concurrent rendering mechanisms, and be able to keep the UI smooth in high-frequency update scenarios.

10. If you are doing AI Chat / large-scale system ​

  • Streaming rendering Hook design
  • Interruptible mechanism
  • Concurrency priority control
  • virtual list
  • State Hierarchy