前端开发

React 开发最佳实践指南(2024 版)

从组件设计到状态管理,从性能优化到代码规范,全面总结 React 开发中的最佳实践。

站长 12 分钟阅读

React 开发最佳实践指南(2024 版)

本文总结了在 React 项目中经过实践验证的开发模式和最佳实践,帮助你写出更优雅、更高效的代码。

1. 组件设计原则

单一职责原则

每个组件只做一件事。如果一个组件变得太复杂,考虑将其拆分为更小的子组件。

// ❌ 不好:一个组件做了太多事情
function UserDashboard({ users }) {
  const [filter, setFilter] = useState('')
  const [sort, setSort] = useState('name')
  // 过滤、排序、渲染表格、处理分页...全在一个组件里
}

// ✅ 好:拆分职责
function UserDashboard({ users }) {
  const { filteredUsers, filter, setFilter } = useUserFilter(users)
  return (
    <div>
      <FilterBar filter={filter} onChange={setFilter} />
      <UserTable users={filteredUsers} />
    </div>
  )
}

组件分类

类型说明示例
页面组件路由对应的顶层组件HomePage, AboutPage
容器组件管理数据和状态UserListContainer
展示组件纯 UI 渲染Button, Card, Avatar
Hook可复用的逻辑useAuth, useFetch

2. 状态管理策略

状态分类

React 中的状态可以分为三类:

  1. 组件局部状态 — 用 useState / useReducer
  2. 跨组件共享状态 — 用 Context 或状态库
  3. 服务端状态 — 用 React Query / SWR
// 局部状态:useState
const [isOpen, setIsOpen] = useState(false)

// 复杂局部状态:useReducer
const [state, dispatch] = useReducer(reducer, initialState)

// 服务端状态:React Query
const { data, isLoading } = useQuery({
  queryKey: ['users'],
  queryFn: fetchUsers
})

不要过度使用全局状态

很多状态其实不需要全局化。在决定使用全局状态前,问自己:

  • 这个状态需要被多个不相关组件访问吗?
  • 状态更新是否需要跨组件协调
  • 是否有性能问题需要考虑?

如果答案都是否,那就用局部状态。

3. 性能优化

React.memo 的正确使用

// 只在 props 真正不变时才有意义
const ExpensiveItem = React.memo(function ExpensiveItem({ item }) {
  return <div>{/* 复杂渲染 */}</div>
})

useMemo 和 useCallback

  • useMemo:缓存计算结果
  • useCallback:缓存函数引用
// 缓存昂贵计算
const sortedList = useMemo(() => 
  heavySort(rawList), [rawList]
)

// 缓存传给子组件的回调
const handleClick = useCallback((id) => {
  setSelected(id)
}, [])

注意:不要滥用这些 Hook。简单的计算和渲染不需要优化,过度使用反而会增加开销。

4. 自定义 Hook 复用逻辑

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key)
      return item ? JSON.parse(item) : initialValue
    } catch {
      return initialValue
    }
  })

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(value))
  }, [key, value])

  return [value, setValue]
}

5. 错误处理

Error Boundary

class ErrorBoundary extends React.Component {
  state = { hasError: false }

  static getDerivedStateFromError(error) {
    return { hasError: true }
  }

  render() {
    if (this.state.hasError) {
      return <FallbackComponent />
    }
    return this.props.children
  }
}

总结

  • 保持组件小而专注
  • 状态管理从局部开始,需要时再提升
  • 性能优化按需进行,不要过早优化
  • 自定义 Hook 复用逻辑
  • 始终做好错误处理

希望这些实践能帮助你构建更好的 React 应用!🚀