Skip to content

Next.js 13 App Router 预览

最近在团队中落地Next.js 13 App Router 预览,积累了不少经验。整理出来供参考,希望对做类似工作的同学有所帮助。

核心概念

先来看基本的实现方式:

javascript
import { useRef, useEffect, useState } from 'react'

function useIntersectionObserver(options = {}) {
  const [isVisible, setIsVisible] = useState(false)
  const ref = useRef(null)

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      setIsVisible(entry.isIntersecting)
    }, { threshold: 0.1, ...options })
    const el = ref.current
    if (el) observer.observe(el)
    return () => { if (el) observer.unobserve(el) }
  }, [])

  return [ref, isVisible]
}

这段代码展示了基本的使用方式。实际项目中还需要考虑错误处理和边界条件。

深度解析

在这个基础上,我们可以进一步优化:

javascript
import { useState, useEffect, useCallback } from 'react'

function DataList({ endpoint, pageSize = 20 }) {
  const [data, setData] = useState([])
  const [page, setPage] = useState(1)
  const [loading, setLoading] = useState(false)

  const fetchData = useCallback(async () => {
    setLoading(true)
    try {
      const res = await fetch(`${endpoint}?page=${page}&size=${pageSize}`)
      setData(await res.json())
    } finally { setLoading(false) }
  }, [endpoint, page, pageSize])

  useEffect(() => { fetchData() }, [fetchData])

  return <div>{loading ? <Spinner /> : <List items={data} />}</div>
}

这种模式在大型项目中非常实用,能显著降低维护成本。

落地经验

实际项目中的用法会更复杂一些:

javascript
import { Suspense } from 'react'
import { UserList } from './components/UserList'

export default async function HomePage() {
  return (
    <main className="container mx-auto p-4">
      <h1>控制台</h1>
      <Suspense fallback={<Skeleton />}>
        <UserList />
      </Suspense>
    </main>
  )
}

通过这种方式,代码的可测试性和可扩展性都得到了提升。

调优策略

以下是一个完整的示例:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

注意边界条件处理,这在生产环境中至关重要。

小结

  • 生产环境使用前务必做好兼容性验证
  • 团队协作中约定和文档比技术本身更重要
  • 关注社区动态,技术方案需要持续迭代

MIT Licensed