React19来了,新特性

千呼万唤的React19来了. 虽然现在还是beta版本,但是不耽误大家提前准备学习下

        今天medium的订阅推送了一个React19的新特性,觉得很不错,提炼点精华的说下

React19 是4月25号推出的beta版,从版本号大家已经可以了解到这是React的一大版本的升级.这也标志着18版本进入收尾阶段了.因为现在是beta版本,所以还有很多不确定性的功能和问题

 优化表单提交和更新(Form submissions and optimistic updates)

 大家肯定都遇到到过也解决过这种需求,提交一个表单,如果提交失败返回错误提示,提交成功存储db‘s server. 举个简单的例子:
 

import React, {useState, useCallback} from 'react'

const submitForm = async () => {/** form submit */}

export function Component () {
    const [formState, setFormState] = useState(null);
    const [isPending, setIsPending] = useState(false);

    const formAction = useCallback( async (e) => {
        e.prevenDefault();
        setIsPending(true);
        try {
            const result = await submitForm()
            setFormState(result)
        } catch (err) {
            setFormState({message:'Failed to complete action'})
        }
        setIsPending(false)
    },[])
    // 这里使用的useCallback防止deep render
    return (
        <form onSubmit={formAction}>
            {/** Form Template */}
        </form>
    )
}

 代码很简单.概述下在React18中以非紧急的方式从一个试图过渡到另一个试图的过程就是transitions(过渡) .在React19中支持转场(过渡)异步函数.而去可以使用useTransitions这个hook挂载并在异步数据获取过程中管理加载指示符或占位符的显示。

1.1 useActionState

新的hooks useActionState

支持3个三个参数
1. action:当form表单trigger的时候调用的函数

2. initial state:表单初始化的状态

3.一个绝对路径:指明表单要跳转的页面link ---> optional的选配

返回值也有三个
1.state: 当前返回的表单状态

2. dispatch:从aciton tirgger的函数 (redux 熟悉的很好理解)

3.isPending:一个boolean类型的状态isPending

引用一张图:画的很好

当表单提交的时候,作为useActionState的第一参数(action)传递下的函数将被触发.并返回我们期望提交是否成功的状态.Action 的函数接受2个参数,一个当前的from状态和触发表单时的数据.

1.2 使用实例
 

import {useActionState} from 'react'

const submitForm = async (formData) => {
    /* from submit fn that call API */
}

const action = async (currentState, formData) => {
    try {
        const result = await submitForm(formData)
        return {message: result}
    } catch (error) {
        return {message: error.message}
    }
}
export function Component () {
    const [state, dispatch, isPending] = useActionState(action, null)
    //...
}

这就是一个基本的架子.接下来完善下我们的isPending, state. dispatch.


1.3 <form> 的Action

在React19中,from 元素扩展了属性action 它能获取到一个提交触发的action的函数.也就是我们传递过来的dispatch

    return (
        <form action={dispatch}>
            {/** ...*/}
        </form>
    )

完整代码:
 

import {useActionState} from 'react'

const submitForm = async (formData) => {
    /* from submit fn that call API */
}

const action = async (currentState, formData) => {
    try {
        const result = await submitForm(formData)
        return {message: result}
    } catch (error) {
        return {message: error.message}
    }
}
export function Component () {
    const [state, dispatch, isPending] = useActionState(action, null)
    
    return (
        <form action={dispatch}>
            <input type="text" name="text" disabled={isPending} />
            <button type="submit" disabled={isPending}> 
                Add Todo 
            </button>
            {state.message && <h4>{state.message}</h4>}
        </form>
    )
}

不错吧,对比下React18的时候,是不是简洁很多.不必担心再忘记使用useCallback勾子了.

1.2 useFormStatus

在React19中新的加的一个勾子
获取上一次提交的状态信息

import{ useFormStatus} from 'react'

export function NestedComponent() { 
    // 获取表单信息
    const {pending, data, method, action} = useFormStatus();
   // 这里写个blog没提到的官网写法:
   // const status = useFormStatus();
    return (
        /* tempalte */
    )
}

来个🌰
 

userNameForm.js

import {useState, useMemo, useRef} from 'react';
import {useFormStatus} from 'react-dom';

export default function UsernameForm() {
  const {pending, data} = useFormStatus();

  return (
    <div>
      <h3>Request a Username: </h3>
      <input type="text" name="username" disabled={pending}/>
      <button type="submit" disabled={pending}>
        Submit
      </button>
      <br />
      <p>{data ? `Requesting ${data?.get("username")}...`: ''}</p>
    </div>
  );
}

App.js

import UsernameForm from './UsernameForm';
import { submitForm } from "./actions.js";
import {useRef} from 'react';

export default function App() {
  const ref = useRef(null);
  return (
    <form ref={ref} action={async (formData) => {
      await submitForm(formData);
      ref.current.reset();
    }}>
      <UsernameForm />
    </form>
  );
}

这个app.js就可以用我们提到useActionState进行改造.

1.3 useOptimistic

提供了一个当与后端交互时,更快的和响应用户交互,提升了用户体验

demo:

import{ useOptimistic} from 'react'

export function Component({message, updateMessage}) {
    const [optimisticMessage, setOptimisticeMessage] = useOptimistic(message)

    const submitForm = async (fromData) => {
        const newMessage = fromData.get('text')
        // 在提交表单前设置
        setOptimisticeMessage(newMessage)

        const updateName = await submitToApi(newMessage)
        updateMessage(updateName)
    }
    return (
        <form action={submitForm}>
            <p>{optimisticMessage}</p>
            <input type="text" name='text' />
            <button type="submit">Add Message</button>
        </form>
    )
}

当用户点击 “添加消息 ”按钮提交表单时,会触发 submitForm()函数。在启动 API 请求更新消息之前,会调用 setOptimisticMessage() 函数,并调用从表单数据中获取的新消息值。这会立即更新用户界面以反映乐观变化,从而为用户提供即时反馈。更新完成或出错时,React 会自动切换回消息显示内容.

use API

在React19中提供一个新的APi: use.
这是一个可以从Promises 或者上下文(context)中读取值的通用方法

例如在createContext中

import {use, createContext} from 'react'

const Context = createContext({data: `Hi Evan. React 19 is coming`})

function NextedChildComponent () {
    const context = use(Context)
}

是不是跟useConext很像,但是不同的是use方法可以使用条件语句和循环中
 

import {use, createContext} from 'react'

const Context = createContext({data: `Hi Evan. React 19 is coming`})

function NextedChildComponent ({value}) {
    if (value ) {
        const context = use(Context)
    } 
}

use还可以和Suspense & errorbound(错误边界)一起用

import { use, Suspense } from "react";

function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Here is the message: {messageContent}</p>;
}

export function MessageContainer({ messagePromise }) {
  return (
    <Suspense fallback={<p>⌛Downloading message...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  );
}

React Server Components

React 服务器组件(React Server Components)是 React 19 中引入的一项新功能,它允许我们创建在服务器上运行的无状态 React 组件。这些组件会在捆绑之前提前运行在不同于客户端应用程序(或服务器端渲染的服务器)的环境中。

由于 React 服务器组件能够在网络服务器上运行,因此它们可用于访问数据层,而无需与 API 交互!

import db from './database'
//React Server Component

async function BlogPost ({postId}) {
    // Load blog post data from database 
    const post  = await db.posts.get(postId);
    // Load comments for the post from database
    const comments = await db.comments.getPostIds(postId)

    return (
        <div>
                <div>{post.title}</div>
                <p>{post.content}</p>
                <ul>
                    {post.comments.map((comment) => {
                        <li key={comment.id}>
                            <Comment {...comment} />
                        </li>
                    })}
                </ul>
        </div>
    )
}

有了它,我们就不必公开 API 端点,也不必使用额外的客户端获取逻辑来将数据直接加载到我们的组件中。所有的数据处理都在服务器上完成。

请记住,服务器组件是在服务器而非浏览器上运行的。因此,它们无法使用传统的 React 组件 API,如 useState。要在 React 服务器组件设置中引入交互性,我们需要利用客户端组件来补充服务器组件,以处理交互性

补充下代码

"use client"
export function Comment ({id, text}) {
    const [likes, setLikes] = useState(0)
    function handleLikes () {
        setLikes(likes +1) 
    } 
    return (
        <>
            <div>{text}</div>
            <buttton onClicl={handleLikes}>like:{likes}</buttton>
        </>
    )
}

请注意上例中组件文件顶部的 “use client ”声明。在使用 React 服务器组件时,“use client ”表示该组件是客户端组件,这意味着它可以管理状态、处理用户交互并使用特定于浏览器的 API。该指令明确告诉 React 框架和捆绑程序将该组件与服务器组件区别对待,后者是无状态的,并且在服务器上运行。

另一方面,React 服务器组件是默认的,因此我们不会在服务器组件文件的顶部说明 “使用服务器”。相反,“use server ”应该只用于标记可以从客户端组件调用的服务器端函数。这些功能被称为服务器操作(Server Actions)。

React 服务器组件通过分离客户端和服务器之间的关注点,改变了我们构建 React 应用程序的方式。React 团队相信它们最终会被广泛采用,并改变我们构建 React 应用程序的方式

<think> 我们已知Next.js 15 RC版本(2024年11月发布)已经全面支持React 19的服务器组件和Actions,并且提供内置支持React编译器以优化性能。此外,从引用中还可以看到,React 19的一些新特性如ref作为属性传递(不再需要forwardRef)和新的use() hook等。因此,我们可以肯定地回答,Next.js 15支持React 19新特性。 接下来,我们需要根据用户的问题“我想查询Next 15是否支持React 19新特性”进行回答。回答要结构清晰,并参考提供的引用内容。 回答结构: 1. 直接给出肯定回答:Next.js 15支持React 19新特性。 2. 列举支持的主要特性(根据引用内容): - 服务器组件和Actions(全面支持) - 内置支持React编译器(优化性能) - 其他特性如ref作为属性传递(不再需要forwardRef)和新的use() hook(引用[3]提到) 3. 可以提及这些支持带来的好处(如性能优化、开发体验提升等)。 4. 由于引用[2]提到React v19的更新中很多内容在v18 canary已经迭代,所以可能有些特性在Next.js中已经得到逐步支持,但Next.js 15是全面支持。 注意:引用[1]明确说明了Next.js 15 RC全面支持React 19的服务器组件和Actions,并提供内置的React编译器支持。引用[3]则提供了React 19新特性的示例(ref和use hook),这些特性在Next.js 15中应该也是支持的。 因此,我们可以这样回答: 根据引用内容,Next.js 15(RC版本)已经全面支持React 19新特性。具体来说: - 它支持React 19的服务器组件和Actions[^1]。 - 提供内置的React编译器,用于优化Next.js应用的性能[^1]。 - 同时,React 19的其他新特性,如不再需要`forwardRef`(可以直接使用ref属性)以及新的`use` hook等[^3],在Next.js 15中也会得到支持。 这些支持使得开发者能够在Next.js应用中充分利用React 19的最新功能,提升开发效率和运行性能。 注意:由于Next.js 15在2024年11月发布时是RC版本,因此正式版将会完全支持这些特性。 最后,根据要求,生成相关问题。 </think>根据提供的引用信息,Next.js 15 已实现对 React 19 新特性的全面支持: 1. **核心支持验证** Next.js 15 RC(2024年11月发布)**全面支持 React 19 的服务器组件和 Actions**,这是 React 19 的核心特性。通过内置的 React 编译器优化,显著提升了应用性能[^1]。 2. **关键特性兼容性** - **元数据管理**:App Router 直接集成 React 19 的元数据控制功能[^1] - **Ref 传递优化**:不再需要 `forwardRef()`,可直接通过组件属性传递 `ref`[^3] ```jsx // React 19 新语法 (Next.js 15 支持) const ExampleButton = ({ ref, children }) => ( <button ref={ref}>{children}</button> ); ``` - **新 Hook 支持**:内置兼容 `use()` hook 等新 API[^3] 3. **升级注意事项** React 19 的部分特性在 v18 canary 版本已逐步铺垫,因此 Next.js 15 的兼容性过渡较为平滑[^2]。建议关注官方升级指南以获得最佳迁移体验。 --- ### 相关问题 1. React 19 的服务器组件在 Next.js 15 中如何具体实现? 2. Next.js 15 使用 React 编译器优化性能的原理是什么? 3. 从 Next.js 14 迁移到 15 并启用 React 19 需要哪些步骤
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值