React 19 的 3 个杀手级特性:我的代码量减少了 40%
React 19 正式版发布后,我花了两个周末把公司的核心项目迁移过去。结果意外地好——三个新特性直接让组件代码减少了约 40%。
1. Actions 和 useActionState
这是 React 19 最大的变化。以前处理表单异步提交需要手动管理 loading、error、data 三个状态:
TSX
// React 18 - 手动管理三个状态
function OldForm() {
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [data, setData] = useState<Result | null>(null)
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)
setError(null)
try {
const result = await submitForm(formData)
setData(result)
} catch (err) {
setError(err.message)
} finally {
setLoading(false)
}
}
// ...JSX
}
// React 19 - useActionState 一个 Hook 搞定
function NewForm() {
const [state, formAction, pending] = useActionState(
async (prevState, formData) => {
const result = await submitForm(formData)
return { data: result }
},
null
)
return (
<form action={formAction}>
<input name="title" />
<button disabled={pending}>
{pending ? '提交中...' : '提交'}
</button>
{state?.data && <Success data={state.data} />}
</form>
)
}2. useOptimistic
乐观更新终于有了原生支持:
TSX
function TodoList({ initialTodos }: { initialTodos: Todo[] }) {
const [todos, addOptimisticTodo] = useOptimistic(
initialTodos,
(state, newTodo: Todo) => [...state, newTodo]
)
const handleAdd = async (formData: FormData) => {
const title = formData.get('title') as string
// 立即显示
addOptimisticTodo({ id: 'temp', title, done: false })
// 后台提交
await createTodo(title)
}
return (
<>
<form action={handleAdd}>
<input name="title" />
<button>添加</button>
</form>
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</>
)
}3. ref 作为 prop
终于不用 forwardRef 了:
TSX
// React 18 - 必须用 forwardRef
const Input = forwardRef<HTMLInputElement, Props>((props, ref) => {
return <input ref={ref} {...props} />
})
// React 19 - ref 就是普通 prop
function Input({ ref, ...props }: Props & { ref: Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />
}迁移实践
升级 React 19 很简单:
BASH
npm install react@19 react-dom@19
npm install @types/react@latest @types/react-dom@latest迁移过程遇到的主要问题:
1. forwardRef 改为 ref prop
2. useFormState 改名为 useActionState
3. Suspense 行为微调
总体迁移成本很低,收益明显。
读者评论 2