当前位置:首页 > 科技  > 软件

React 19 即将推出的四个全新 Hooks,很实用!

来源: 责编: 时间:2024-01-26 17:06:47 322观看
导读近日,React 团队成员在社交平台表示,团队正在开发 React v19 版本,并且没有计划发布 v18.3 版本。图片React 19 预计将推出 4 个全新 Hooks,这些 Hooks 主要关注 React 中的两个痛点:数据获取和表单。 这些 Hooks 目前在 R

近日,React 团队成员在社交平台表示,团队正在开发 React v19 版本,并且没有计划发布 v18.3 版本。1HK28资讯网——每日最新资讯28at.com

图片图片1HK28资讯网——每日最新资讯28at.com

React 19 预计将推出 4 个全新 Hooks,这些 Hooks 主要关注 React 中的两个痛点:数据获取和表单。 这些 Hooks 目前在 React 预览版本中作为实验性 API 提供,预计会成为 React 19 的一部分,但是最终发布之前,API 可能会有所变化。1HK28资讯网——每日最新资讯28at.com

新的 Hooks 包括:1HK28资讯网——每日最新资讯28at.com

  • use
  • useOptimistic
  • useFormState
  • useFormStatus

use

use 是一个实验性 React Hook,它可以让读取类似于 Promise 或 context 的资源的值。1HK28资讯网——每日最新资讯28at.com

const value = use(resource);

官方文档:https://zh-hans.react.dev/reference/react/use1HK28资讯网——每日最新资讯28at.com

use(Promise)

use 可以在客户端进行“挂起”的 API。可以将一个 promise 传递给它,React 将会在该 promise 解决之前进行挂起。它的基本语法如下:1HK28资讯网——每日最新资讯28at.com

import { use } from 'react';function MessageComponent({ messagePromise }) {    const message = use(messagePromise);    // ...}

下面来看一个简单的例子:1HK28资讯网——每日最新资讯28at.com

import * as React from 'react';import { useState, use, Suspense } from 'react';import { faker } from '@faker-js/faker';export const App = () => {  const [newsPromise, setNewsPromise] = useState(() => fetchNews());  const handleUpdate = () => {    fetchNews().then((news) => {      setNewsPromise(Promise.resolve(news));    });  };  return (    <>      <h3>        新闻列表    		<button onClick={handleUpdate}>刷新</button>      </h3>      <NewsContainer newsPromise={newsPromise} />    </>  );};let news = [...new Array(4)].map(() => faker.lorem.sentence());const fetchNews = () =>  new Promise<string[]>((resolve) =>    // 使用 setTimeout 模拟数据获取    setTimeout(() => {      // 每次刷新时添加一个标题      news.unshift(faker.lorem.sentence());      resolve(news);    }, 1000)  );const NewsContainer = ({ newsPromise }) => (  <Suspense fallback={<p>请求中...</p>}>    <News newsPromise={newsPromise} />  </Suspense>);const News = ({ newsPromise }) => {  const news = use<string[]>(newsPromise);  return (    <ul>      {news.map((title, index) => (        <li key={index}>{title}</li>      ))}    </ul>  );};

在上面的例子中,每次刷新时,都会先显示“请求中...”,请求到数据后进行展示:1HK28资讯网——每日最新资讯28at.com

图片图片1HK28资讯网——每日最新资讯28at.com

官方文档中,关于 <Suspense> 有一个警告:1HK28资讯网——每日最新资讯28at.com

目前尚不支持在不使用固定框架的情况下进行启用 Suspense 的数据获取。实现支持 Suspense 数据源的要求是不稳定的,也没有文档。React 将在未来的版本中发布官方 API,用于与 Suspense 集成数据源。1HK28资讯网——每日最新资讯28at.com

在新版本中,use 可能就是用于与 Suspense 集成数据源的官方 API。1HK28资讯网——每日最新资讯28at.com

这个全新的use hook 与其他 Hooks 不同,它可以在循环和条件语句中像 if 一样被调用。这意味着我们可能不再需要依赖像 TanStack Query 这样的第三方库在客户端进行数据获取。然而,这仍需进一步观察,因为 Tanstack Query 的功能远不止解析 Promise 这么简单。1HK28资讯网——每日最新资讯28at.com

use(Context)

这个 use hook 也可以用来读取 React Context。它与 useContext 作用完全相同,只是可以在循环(如 for)和条件语句(如 if)中调用。1HK28资讯网——每日最新资讯28at.com

import { use } from 'react';function HorizontalRule({ show }) {    if (show) {        const theme = use(ThemeContext);        return <hr className={theme} />;    }    return false;}

这将简化某些场景下的组件层级结构,因为在循环或条件语句中读取 context,之前唯一的方法就是将组件一分为二。1HK28资讯网——每日最新资讯28at.com

在性能方面,这一改进也是巨大的进步,因为现在即使 context 发生变化,我们也可以有条件地跳过组件的重新渲染。1HK28资讯网——每日最新资讯28at.com

useOptimistic

useOptimistic Hook 允许在进行提交动作的同时,能够乐观地更新用户界面,提升用户体验。其语法如下:1HK28资讯网——每日最新资讯28at.com

import { useOptimistic } from 'react';function AppContainer() {    const [optimisticState, addOptimistic] = useOptimistic(        state,        // 更新函数        (currentState, optimisticValue) => {            // 合并并返回带有乐观值的新状态          },    );}

乐观更新:一种更新应用程序中数据的策略。这种策略通常会先更改前端页面,然后向服务器发送请求,如果请求成功,则结束操作;如果请求失败,则页面回滚到先前状态。这种做法可以防止新旧数据之间的跳转或闪烁,提供更快的用户体验。1HK28资讯网——每日最新资讯28at.com

下面来看一个添加购物车的例子:1HK28资讯网——每日最新资讯28at.com

import { useState, useOptimistic } from 'react';const AddToCartForm = ({ id, title, addToCart, optimisticAddToCart }) => {  const formAction = async (formData) => {    optimisticAddToCart({ id, title });    try {      await addToCart(formData, title);    } catch (e) {      // 捕获错误    }  };  return (    <form action={formAction}>      <h2>{title}</h2>      <input type="hidden" name="itemID" value={id} />      <button type="submit">添加到购物车</button>    </form>  );};type Item = {  id: string;  title: string;};const Cart = ({ cart }: { cart: Item[] }) => {  if (cart.length == 0) {    return null;  }  return (    <>      购物车:      <ul>        {cart.map((item, index) => (          <li key={index}>{item.title}</li>        ))}      </ul>      <hr />    </>  );};export const App = () => {  const [cart, setCart] = useState<Item[]>([]);  const [optimisticCart, optimisticAddToCart] = useOptimistic<Item[], Item>(    cart,    (state, item) => [...state, item]  );  const addToCart = async (formData: FormData, title) => {    const id = String(formData.get('itemID'));    await new Promise((resolve) => setTimeout(resolve, 1000));    setCart((cart: Item[]) => [...cart, { id, title }]);    return { id };  };  return (    <>      <Cart cart={optimisticCart} />      <AddToCartForm        id="1"        title="JavaScript权威指南"        addToCart={addToCart}        optimisticAddToCart={optimisticAddToCart}      />      <AddToCartForm        id="2"        title="JavaScript高级程序设计"        addToCart={addToCart}        optimisticAddToCart={optimisticAddToCart}      />    </>  );};

在上面的例子中,将商品添到购物车时,会先在购物车列表看到刚刚添加的商品,而不必等到数据请求完成。这样,用户可以更快地看到更新后的购物车内容,提供更加流畅的用户体验。1HK28资讯网——每日最新资讯28at.com

图片图片1HK28资讯网——每日最新资讯28at.com

useFormState

在介绍这个 Hook 之前,先来看以下这个 Hook 使用的背景。1HK28资讯网——每日最新资讯28at.com

<form>

React 将引入一个新组件:<form>,它是创建用于提交信息的交互式控件,可以将一个函数作为action的属性值。当用户提交表单时,React 将自动调用此函数,以执行相应的操作。1HK28资讯网——每日最新资讯28at.com

<form actinotallow={handleSubmit} />

注意,如果在 React 18 中添加<form action>属性,就会收到警告:1HK28资讯网——每日最新资讯28at.com

⚠️ Warning: Invalid value for prop action on <form> tag. Either remove it from the element or pass a string or number value to keep it in the DOM.1HK28资讯网——每日最新资讯28at.com

这里的意思是,<form>标签上的 prop action无效。要么从元素中删除它,要么传递一个字符串或数字值以将其保留在 DOM 中。1HK28资讯网——每日最新资讯28at.com

而在新版本中,可以直接在<form>标签上设置action属性。例如,在上面的购物车例子中,:1HK28资讯网——每日最新资讯28at.com

const AddToCartForm = ({ id, title, addToCart }) => {  const formAction = async (formData) => {    try {      await addToCart(formData, title);    } catch (e) {      // 捕获错误    }  };  return (    <form action={formAction}>      <h2>{title}</h2>      <input type="hidden" name="itemID" value={id} />      <button type="submit">添加到购物车</button>    </form>  );};

addToCart 函数并不是在服务器端执行的,而是在客户端(例如用户的浏览器)上运行的。这个函数可以是一个异步函数,如网络请求,而不阻止其他代码的执行。通过使用addToCart函数,开发者可以更简单地处理React中的AJAX表单,例如在搜索表单中。然而,这可能还不足以完全摆脱像 React Hook Form 这样的第三方库,因为它们不仅处理表单提交,还包括验证、副作用等多种功能。1HK28资讯网——每日最新资讯28at.com

看完这个新功能,下面就来看看这一部分要介绍的新 Hook:useFormState。1HK28资讯网——每日最新资讯28at.com

useFormState

useFormState 是一个可以根据某个表单动作的结果更新 state 的 Hook。1HK28资讯网——每日最新资讯28at.com

const [state, formAction] = useFormState(fn, initialState);

只有在表单提交触发 action 后才会被更新的值,如果该表单没有被提交,该值会保持传入的初始值不变。1HK28资讯网——每日最新资讯28at.com

例如,这可以用来显示由表单操作返回的确认消息或错误消息。1HK28资讯网——每日最新资讯28at.com

import { useState } from 'react';import { useFormState } from 'react-dom';const AddToCartForm = ({ id, title, addToCart }) => {  const addToCartAction = async (prevState, formData) => {    try {      await addToCart(formData, title);      return '添加成功';    } catch (e) {      return "添加失败:卖完啦";    }  };  const [message, formAction] = useFormState(addToCartAction, null);  return (    <form action={formAction}>      <h2>{title}</h2>      <input type="hidden" name="itemID" value={id} />      <button type="submit">添加到购物车</button>       {message}    </form>  );};type Item = {  id: string;  title: string;};export const App = () => {  const [cart, setCart] = useState<Item[]>([]);  const addToCart = async (formData: FormData, title) => {    const id = String(formData.get('itemID'));    await new Promise((resolve) => setTimeout(resolve, 1000));    if (id === '1') {      setCart((cart: Item[]) => [...cart, { id, title }]);    } else {      throw new Error('Unavailable');    }    return { id };  };  return (    <>      <AddToCartForm        id="1"        title="JavaScript权威指南"        addToCart={addToCart}      />      <AddToCartForm        id="2"        title="JavaScript高级程序设计"        addToCart={addToCart}      />    </>  );};

效果如下:1HK28资讯网——每日最新资讯28at.com

图片图片1HK28资讯网——每日最新资讯28at.com

注意:useFormState 需要从 react-dom 中导入,而不是从 react 中导入。1HK28资讯网——每日最新资讯28at.com

useFormStatus

useFormStatus 用于获取上次表单提交的状态信息。1HK28资讯网——每日最新资讯28at.com

const { pending, data, method, action } = useFormStatus();

它不接收任何参数,会返回一个包含以下属性的 status 对象:1HK28资讯网——每日最新资讯28at.com

  • pending:布尔值。如果为 true,则表示父级 <form> 正在等待提交;否则为 false。
  • data:包含父级 <form> 正在提交的数据;如果没有进行提交或没有父级 <form>,它将为 null。
  • method:字符串,可以是 'get' 或 'post'。表示父级 <form> 使用 GET 或 POST HTTP 方法 进行提交。默认情况下,<form> 将使用 GET 方法,并可以通过 method 属性指定。
  • action:一个传递给父级 <form> 的 action 属性的函数引用。如果没有父级 <form>,则该属性为 null。如果在 action 属性上提供了 URI 值,或者未指定 action 属性,status.action 将为 null。

下面来继续看购物车的例子,将商品添加到购物车成功前,禁用添加按钮:1HK28资讯网——每日最新资讯28at.com

import { useState } from 'react';import { useFormStatus } from 'react-dom';const AddToCartForm = ({ id, title, addToCart }) => {  const formAction = async (formData) => {    try {      await addToCart(formData, title);    } catch (e) {      // 捕获错误    }  };  return (    <form action={formAction}>      <h2>{title}</h2>      <input type="hidden" name="itemID" value={id} />      <SubmitButton />    </form>  );};const SubmitButton = () => {  const { pending } = useFormStatus();  return (    <button disabled={pending} type="submit">      添加到购物车    </button>  );};type Item = {  id: string;  title: string;};const Cart = ({ cart }: { cart: Item[] }) => {  if (cart.length == 0) {    return null;  }  return (    <>      购物车:      <ul>        {cart.map((item, index) => (          <li key={index}>{item.title}</li>        ))}      </ul>      <hr />    </>  );};export const App = () => {  const [cart, setCart] = useState<Item[]>([]);  const addToCart = async (formData: FormData, title) => {    const id = String(formData.get('itemID'));    await new Promise((resolve) => setTimeout(resolve, 1000));    setCart((cart: Item[]) => [...cart, { id, title }]);    return { id };  };  return (    <>      <Cart cart={cart} />      <AddToCartForm        id="1"        title="JavaScript权威指南"        addToCart={addToCart}      />      <AddToCartForm        id="2"        title="JavaScript高级程序设计"        addToCart={addToCart}      />    </>  );};

添加购物车时效果如下:1HK28资讯网——每日最新资讯28at.com

图片图片1HK28资讯网——每日最新资讯28at.com

注意:useFormState 需要从 react-dom 中导入,而不是从 react 中导入。此外,它仅在父级表单使用 action 属性时才有效。1HK28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-69007-0.htmlReact 19 即将推出的四个全新 Hooks,很实用!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 如何让Go程序以后台进程或daemon方式运行

下一篇: Seata如何实现两阶段提交(2PC)分布式事务

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 一文掌握 Golang 模糊测试(Fuzz Testing)

    模糊测试(Fuzz Testing)模糊测试(Fuzz Testing)是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。可以用来发现应用程序、操作系统和网络协议等中的漏洞或
  • 三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • 零售大模型“干中学”,攀爬数字化珠峰

    文/侯煜编辑/cc来源/华尔街科技眼对于绝大多数登山爱好者而言,攀爬珠穆朗玛峰可谓终极目标。攀登珠峰的商业路线有两条,一是尼泊尔境内的南坡路线,一是中国境内的北坡路线。相
  • 雅柏威士忌多款单品价格大跌,泥煤顶流也不香了?

    来源 | 烈酒商业观察编 | 肖海林今年以来,威士忌市场开始出现了降温迹象,越来越多不断暴涨的网红威士忌也开始悄然回归市场理性。近日,LVMH集团旗下苏格兰威士忌品牌雅柏(Ardbeg
  • 东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一
  • OPPO K11搭载高性能石墨散热系统:旗舰同款 性能凉爽释放

    日前OPPO官方宣布,将于7月25日14:30举办新品发布会,届时全新的OPPO K11将正式与大家见面,将主打旗舰影像,和同档位竞品相比,其最大的卖点就是将配备索尼
  • 最薄的14英寸游戏笔记本电脑 Alienware X14已可以购买

    2022年1月份在国际消费电子展(CES2022)上首次亮相的Alienware新品——Alienware X14现在已经可以购买了,这款笔记本电脑被誉为世界上最薄的 14 英寸游戏笔
Top