React18和React19新特性

4 阅读6分钟

React18核心并发渲染

通过createRoot、useTransition、自动批处理等特性提升应用性能和用户体验,向下兼容,升级成本低

1. 并发渲染(Concurrent Rendering) ---- 底层核心

  • 它允许React的渲染过程被中断、暂停、恢复或放弃,不再是过去“一旦开始就必须执行到底"的同步渲染模式
  • 核心价值:解决长任务阻塞主线程导致的界面卡顿(如大数据渲染、复杂计算时,输入/点击等交互仍能响应)
  • 注意:这是底层能力,无需开发者直接调用,通过后续的useTransition、createRoot等API间接启用

2. 新的根节点API: createRoot(启用新特性的入口)

  • 18废弃了旧的ReactDOM.render,推出createRoot作为新的根节点创建方式,这是启用所有18新特性的前提
// 17及之前
import ReactDOM from 'react-dom'
ReactDOM.render(<APP />, document.getElementById('root'))

// 18推荐
import ReactDOM from 'react-dom/client'
const root = ReactDOM.createRoot(document.getElementById('root))
root.render(<APP />) // 首次渲染
root.unmount() // 新增:优雅卸载组件(替代旧的unmountComponentAtNode)

3. 自动批处理(Automatic Batching) --- 性能优化

  • 批处理值React合并多个状态更新,只触发一次重渲染,减少不必要的DOM操作
  • 18把批处理能力扩展到所有场景(包括异步回调、定时器、Promise等)
// 17 异步回调中会触发2次重渲染
function handleClick(){
	fetch('/api/data').then(() => {
		setCount(c => c + 1)
		setFlag(f => !f)
	})
}
// 18 自动批处理,仅触发1次重渲染
// 无需手动修改代码,框架层面自动完成
// 如需禁用批处理:使用ReactDOM.flushSync(() => { setCount(1) })

4. useTransition --- 区分紧急/非紧急更新

  • 用于标记非紧急更新(如列表筛选、大数据渲染),避免阻塞紧急更新(如输入框打字、按钮点击)提升交互流畅度
import { useTransition, useState } from 'react'
function SearchBox() {
	const [input, setInput] = useState('')
	const [list, setList] = useState([])
	const [isPending, startTransition]  = usetransition() // 加载态 + 标记非紧急更新
	
	const handleChange = (e) => {
		// 紧急更新:输入框内容(优先执行,不卡顿)
		setInput(e.target.value)
		// 非紧急更新:列表筛选(可被中断)
		startTransition(() => {
			const filtered = largeDataList.filter(item => item.includes(e.target.value))
			setList(filtered)
		})
	}
	return (
		<div>
			<input value={input} onChange={handleChange} />
 			{/* 非紧急更新时显示加载态 */}
      		{isPending ? <div>筛选中...</div> : list.map(item => <div key={item}>{item}</div>)}
		</div>
	)
}

5. useDeferredValue --- 延迟更新非紧急状态

  • 效果类似useTransition,但针对单个状态值,适合需要延迟同步的场景(如输入框联想词)
import { useDeferredValue, useSate } form 'react'
function InputWithSuggestion() {
	// 延迟更新:suggestionValue会滞后与input,且更新不阻塞主线程
	const suggestionValue = useDeferredValue(input, {timeoutMs: 200})
	// 基于延迟值渲染联想词(不会阻塞输入)
	const suggestions = getSuggestions(suggestionValue)

	return(
		<div>
			<input value={input} onChange={(e) => setInput(e.target.value)} />
			<div> {suggestions.map(s => <div key={s}> {s} </div>)} </div>
		</div>
	)
}

6. Suspense增强---支持数据加载(实验性)

  • 18正式扩展Suspense的能力,从代码分割延伸到数据加载(需配合React Query、SWR等库或Next.js框架),实现等待数据时显示加载态
import { Suspense } from 'react'
import DataComponent from './DataComponent'
function App() {
	return (
		<div>
			<h1>主内容</h1>
			{/* 数据加载完成前显示fallback */}
			<Suspense fallback={<div>加载数据中...</div>}>
				<DataComponent/>
			</Suspense>
		</div>
	)
}

7. 服务端渲染(SSR)优化

  • 18对SSR做了大幅升级
  • 流式SSR:逐步输出HTML内容,无需等待所有数据加载完成,提升首屏渲染速度
  • Suspense配合SSR:支持服务端渲染时的加载态显示,避免首屏空白

8.严格模式增强

  • 18的严格模式会模拟组件挂载-卸载-重新挂载的过程,检测非幂等的副作用(如未清理的定时器、重复的请求),帮助开发者写出更健壮的代码

React19核心是简化开发体验

通过Actions、use()钩子,乐观更新等特性减少样板代码,完善服务器组件,聚焦“更简洁、更原生”的开发模式

1. Actions(核心):统一状态更新与表单处理

  • 彻底重构了表单提交、异步操作的处理方式,替代了传统的useState + useEffect + 事件处理组合,内置了加载态、错误处理、异步兼容能力
  • 自动收集表单数据,无需手动维护onchange
  • 原生支持异步操作,自动管理加载/错误状态
  • 可结合Suspense实现加载态展示
import { useActionState } from 'react';

// 定义 Action 函数(支持异步)
async function submitForm(prevState, formData) {
  // 自动获取表单数据,无需手动绑定
  const username = formData.get('username');
  const password = formData.get('password');

  // 模拟异步请求
  try {
    const res = await fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify({ username, password }),
    });
    if (!res.ok) throw new Error('登录失败');
    return { success: true, error: null };
  } catch (err) {
    return { success: false, error: err.message };
  }
}

function LoginForm() {
  // useActionState 管理 Action 状态:初始值、Action函数、加载态
  const [state, formAction, isPending] = useActionState(
    submitForm,
    { success: false, error: null } // 初始状态
  );

  return (
    <form action={formAction}>
      <input name="username" placeholder="用户名" />
      <input name="password" type="password" placeholder="密码" />
      
      {/* 加载态 */}
      <button type="submit" disabled={isPending}>
        {isPending ? '登录中...' : '登录'}
      </button>
      
      {/* 错误提示 */}
      {state.error && <div style={{ color: 'red' }}>{state.error}</div>}
      {/* 成功提示 */}
      {state.success && <div style={{ color: 'green' }}>登录成功!</div>}
    </form>
  );
}

2. use()钩子:简化异步数据获取

  • 替代了useEffect + useState处理异步数据的模式,允许直接在组件体重消费Promise,配合Suspense实现简洁的一部加载逻辑,无需手动管理加载/完成状态
import { use, Suspense } from 'react';

// 异步获取数据的函数
function fetchUser(userId) {
  return fetch(`/api/users/${userId}`).then(res => res.json());
}

// 消费异步数据的组件
function UserProfile({ userId }) {
  // 直接用 use() 消费 Promise,无需 useEffect
  const user = use(fetchUser(userId));
  return (
    <div>
      <h3>{user.name}</h3>
      <p>邮箱:{user.email}</p>
    </div>
  );
}

// 父组件(用 Suspense 处理加载态)
function App() {
  return (
    <div>
      <h1>用户信息</h1>
      <Suspense fallback={<div>加载用户数据中...</div>}>
        <UserProfile userId="123" />
      </Suspense>
    </div>
  );
}

3. useOptimistic:原生支持乐观更新

  • 乐观更新指:先更新UI反馈用户,再等待后端相应

  • 19内置了useOptimistic钩子,无需手动写临时状态,大幅简化点赞、表单提交等场景的体验优化

    import { useOptimistic, useActionState } from 'react' // 异步提交点赞的Action函数 async function toggleLike(prevState, postId) { await fetch(/api/posts/${postId}/like, {method: 'POST'}) return { liked: !prevState.liked } } function LikeButton({postId}) { // 基础状态管理 const [state, toggleLikeAction] = useActionState(toggleLike, {like: false}) // 乐观更新:先更新UI, 再等请求完成 const [optimisticState, addOptimistic] = useOptimistic( state, (currentState) => ({ ...currentState, liked: !currentState.liked }) ) const handleClick = () => { // 1.立即更新UI 乐观更新 addOptimistic() // 2.发送异步请求 togleLikeAction(postId) } return ( <button onclick={handleClick} style={{color: optimisticState.liked ? 'red' : 'black'}}> { optimisticState.liked ? '取消点赞' : '点赞'} ) }

4. 服务器组件(RSC)正式稳定

  • 19完善了服务器组件(Server Components)的规范和实现,明确区分

  • 服务器组件:运行在服务端,无交互、无副作用,可直接访问数据库,减少客户端包体积

  • 客户端组件:允许在浏览器,支持交互(如点击、输入),需显式标记'use client'

  • 核心价值

    • 减少客户端JS体积,提升首屏加载速度
    • 服务端直接获取数据,避免客户端跨域请求
    • 前后端逻辑复用更简单
  • 在Next.js中使用示例

    // 服务器组件(无需 'use client',默认运行在服务端)
    async function PostList() {
      // 直接在组件中获取数据(服务端执行,无跨域)
      const posts = await fetch('/api/posts').then(res => res.json());
      return (
        <div>
          {posts.map(post => (
            <PostItem key={post.id} post={post} />
          ))}
        </div>
      );
    }
    
    // 客户端组件(需显式标记,支持交互)
    'use client';
    function PostItem({ post }) {
      const [liked, setLiked] = useState(false);
      return (
        <div>
          <h3>{post.title}</h3>
          <button onClick={() => setLiked(!liked)}>
            {liked ? '已点赞' : '点赞'}
          </button>
        </div>
      );
    }
    

5. 实用改进

  • ref转发简化:无需forwardRef,直接通过ref属性传递给子组件,减少样板代码
  • 错误边界增强:支持捕获更多类型的错误(如异步错误),且使用更简单
  • 表单原生增强:支持formAction、formMethod等原生表单属性,无需手动绑定
  • TypeScrit优化:类型定义更精准,减少不必要的类型断言,提升类型推导体验
  • 严格模式改进:更友好的副作用检测,帮助开发者写出更健壮的代码