AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁(yè) > 科技  > 軟件

React 19 全覽,新特性進(jìn)行一次深度的體驗(yàn)學(xué)習(xí)

來(lái)源: 責(zé)編: 時(shí)間:2024-06-14 08:53:46 151觀看
導(dǎo)讀最近 React 發(fā)布了 V19 RC 版本,按照慣例,我們對(duì) React 19 的新特性進(jìn)行一次深度的體驗(yàn)學(xué)習(xí),以便盡快上手新特性。這篇文章,我會(huì)通過(guò)豐富的示例,演示 React 19 的新特性,以及相較于老版本的差異。同時(shí)會(huì)附上自己對(duì)部分新特

inN28資訊網(wǎng)——每日最新資訊28at.com

最近 React 發(fā)布了 V19 RC 版本,按照慣例,我們對(duì) React 19 的新特性進(jìn)行一次深度的體驗(yàn)學(xué)習(xí),以便盡快上手新特性。inN28資訊網(wǎng)——每日最新資訊28at.com

這篇文章,我會(huì)通過(guò)豐富的示例,演示 React 19 的新特性,以及相較于老版本的差異。同時(shí)會(huì)附上自己對(duì)部分新特性的評(píng)價(jià),如有不對(duì),煩請(qǐng)指正。inN28資訊網(wǎng)——每日最新資訊28at.com

本文所有示例代碼可以在這里查看:https://codesandbox.io/p/sandbox/react19-demo-lmygpv[2]inN28資訊網(wǎng)——每日最新資訊28at.com

React 19 的最重要改動(dòng),是新增了幾個(gè) Hook,均是針對(duì) form 和異步網(wǎng)絡(luò)請(qǐng)求通用能力的封裝。有點(diǎn)類似 react-query 的 useQuery[3],或者 ahooks 的 useRequest[4]inN28資訊網(wǎng)——每日最新資訊28at.com

在 React Hooks 中,最基本的網(wǎng)絡(luò)請(qǐng)求我們可能會(huì)這樣寫:inN28資訊網(wǎng)——每日最新資訊28at.com

function BasicDemo() {  const [name, setName] = useState("");  const [error, setError] = useState(null);  const [isPending, setIsPending] = useState(false);  const handleSubmit = async () => {    setIsPending(true);    try {      await updateName(name);      console.log("Name updated successfully");    } catch (e) {      setError(e.message);    }    setIsPending(false);  };  return (    <div>      <input value={name} onChange={(event) => setName(event.target.value)} />      <button onClick={handleSubmit} disabled={isPending}>        Update      </button>      {error && <p>{error}</p>}    </div>  );}

上面是一個(gè)最簡(jiǎn)單的網(wǎng)絡(luò)請(qǐng)求示例,點(diǎn)擊按鈕后,請(qǐng)求 updateName 接口,同時(shí)維護(hù)了 isPending 和 error 兩個(gè)請(qǐng)求相關(guān)的狀態(tài)。inN28資訊網(wǎng)——每日最新資訊28at.com

useTransition 支持異步函數(shù)

useTransition 是 React 18  新增的一個(gè) Hook,主要用來(lái)標(biāo)記低優(yōu)先級(jí)更新,低優(yōu)先級(jí)更新是可以被中斷的。在 React 18 中,useTransition 返回的 isPending 代表這次低優(yōu)先級(jí)的更新正在等待中。inN28資訊網(wǎng)——每日最新資訊28at.com

const [isPending, startTransition] = useTransition();

在 18 中,useTransition 返回的 startTransition 只支持傳遞同步函數(shù),而在 19 中,增加了對(duì)異步函數(shù)的支持。通過(guò)這個(gè)特性,我們可以用來(lái)自動(dòng)維護(hù)異步請(qǐng)求的 isPending 狀態(tài)。代碼如下:inN28資訊網(wǎng)——每日最新資訊28at.com

export default function BasicDemo() {  const [name, setName] = useState("");  const [error, setError] = useState(null);  const [isPending, startTransition] = useTransition();  const handleSubmit = () => {    startTransition(async () => {      try {        await updateName(name);        console.log("Name updated successfully");      } catch (e) {        setError(e.message);      }    });  };  return (    <div>      <input value={name} onChange={(event) => setName(event.target.value)} />      <button onClick={handleSubmit} disabled={isPending}>        Update      </button>      {error && <p>{error}</p>}    </div>  );}

上述寫法有兩個(gè)好處:inN28資訊網(wǎng)——每日最新資訊28at.com

  • 自動(dòng)維護(hù)了 isPending 狀態(tài)。
  • 標(biāo)記 updateName 觸發(fā)的更新為低優(yōu)先更新,不會(huì)阻塞 UI 渲染。

useActionState 管理異步函數(shù)狀態(tài)

useActionState 是 React 19 新增的一個(gè) Hook,用來(lái)管理異步函數(shù),自動(dòng)維護(hù)了 data、action、pending 等狀態(tài)。經(jīng)過(guò) useActionState 改造的代碼如下:inN28資訊網(wǎng)——每日最新資訊28at.com

export default function ActionStateDemo() {  const [name, setName] = useState("");  // 接受一個(gè)異步請(qǐng)求函數(shù),返回 [data、action、pending]  const [error, handleSubmit, isPending] = useActionState(    async (previousState, name) => {      try {        await updateName(name);        console.log("Name updated successfully");        return null;      } catch (e) {        console.log("error");        return e.message;      }    }  );  return (    <div>      <input value={name} onChange={(event) => setName(event.target.value)} />      <button        onClick={() => {          startTransition(() => {            handleSubmit(name);          });        }}        disabled={isPending}      >        Update      </button>      {error && <p>{error}</p>}    </div>  );}

上面代碼乍一看,感覺很熟悉,好像和大家經(jīng)常用的 useRequest、useQuery、useSWR 等都差不多。我們通過(guò) API 來(lái)仔細(xì)了解一下 useActionState。inN28資訊網(wǎng)——每日最新資訊28at.com

const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

返回參數(shù)含義:inN28資訊網(wǎng)——每日最新資訊28at.com

  • state:代表 fn 函數(shù)返回的內(nèi)容,fn 未執(zhí)行時(shí),等于 initialState。
  • formAction:用來(lái)觸發(fā) fn 函數(shù)執(zhí)行,可以直接調(diào)用,也可以傳遞給 form 的 action 屬性。
  • isPending:fn 函數(shù)是否正在執(zhí)行中。

傳入?yún)?shù)含義:inN28資訊網(wǎng)——每日最新資訊28at.com

  • fn:一個(gè)異步函數(shù),接受兩個(gè)參數(shù) previousState和 formData。
  • previousState:代表上一次執(zhí)行 fn 返回的內(nèi)容,首次調(diào)用等于 initialState。
  • formData:代表調(diào)用 formAction 時(shí)傳遞的參數(shù)。
  • initialState:fn 沒執(zhí)行時(shí),默認(rèn)的 state。
  • permalink:一個(gè) URL 字符串,通常和服務(wù)端組件有關(guān)系。(表示暫時(shí)沒看懂干啥的)。

你可以能注意到了上面 demo 中使用了 startTransition 來(lái)包裹調(diào)用 handleSubmit。因?yàn)椴挥?startTransition 來(lái)包裹,useActionState 就沒用。inN28資訊網(wǎng)——每日最新資訊28at.com

官方提供的 demo 是通過(guò) form action 觸發(fā)的 handleSubmit,其內(nèi)置了 startTransition ,所以不需要手動(dòng)設(shè)置。inN28資訊網(wǎng)——每日最新資訊28at.com

<form action={handleSubmit}></form>

有沒有覺得很難用?我是這么覺得的。inN28資訊網(wǎng)——每日最新資訊28at.com

useOptimistic 樂(lè)觀更新

樂(lè)觀更新是一種常見的體驗(yàn)優(yōu)化手段,在發(fā)送異步請(qǐng)求之前,我們默認(rèn)請(qǐng)求是成功的,讓用戶立即看到成功后的狀態(tài)。inN28資訊網(wǎng)——每日最新資訊28at.com

先來(lái)看看官方提供的例子:提交表單更新 name,可以立即將新的 name 更新到 UI 中。請(qǐng)求成功則 UI 不變,請(qǐng)求失敗則 UI 回滾。inN28資訊網(wǎng)——每日最新資訊28at.com

function ChangeName() {  const [name, setName] = useState("");  // 定義樂(lè)觀更新的狀態(tài)  const [optimisticName, setOptimisticName] = useOptimistic(name);  const submitAction = async (formData) => {    const newName = formData.get("name");    // 請(qǐng)求之前,先把狀態(tài)更新到 optimisticLike    setOptimisticName(newName);    try {      await updateName(newName);      // 成功之后,更新最終狀態(tài)      setName(newName);    } catch (e) {      console.error(e);    }  };  return (    <form action={submitAction}>      <p>Your name is: {optimisticName}</p>      <p>        <label>Change Name:</label>        <input type="text" name="name" disabled={name !== optimisticName} />      </p>    </form>  );}

useOptimistic 用來(lái)維護(hù)臨時(shí)狀態(tài),保證 UI 的樂(lè)觀更新。inN28資訊網(wǎng)——每日最新資訊28at.com

const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);

返回參數(shù)含義:inN28資訊網(wǎng)——每日最新資訊28at.com

  • optimisticState:樂(lè)觀更新的狀態(tài),UI 上應(yīng)該始終消費(fèi)這個(gè)狀態(tài)。默認(rèn)等于真正的 state。
  • addOptimistic:更新 optimisticState,可以通過(guò) updateFn 指定更新邏輯。

傳入?yún)?shù)含義:inN28資訊網(wǎng)——每日最新資訊28at.com

  • state:真正的狀態(tài)。
  • updateFn:(currentState, optimisticValue) => newOptimisticState,調(diào)用 addOptimistic 的時(shí)候會(huì)通過(guò)這個(gè)函數(shù)生成新的 optimisticState。

這個(gè) Hook API 看起來(lái)還是挺簡(jiǎn)單的。inN28資訊網(wǎng)——每日最新資訊28at.com

但是關(guān)于上面的 Demo 示例,我有個(gè)困惑:如果請(qǐng)求失敗了,是怎么讓狀態(tài)回滾呢?inN28資訊網(wǎng)——每日最新資訊28at.com

經(jīng)過(guò)測(cè)試,上面的代碼確實(shí)有失敗狀態(tài)回滾的能力。inN28資訊網(wǎng)——每日最新資訊28at.com

其奧秘就是異步函數(shù)執(zhí)行結(jié)束后,無(wú)論是成功還是失敗,optimisticName 都會(huì)重置成和最新 state 一樣。inN28資訊網(wǎng)——每日最新資訊28at.com

也就是我們調(diào)用了 setName(newName),那 optimisticName 就變成新的狀態(tài)。如果沒調(diào)用,則變成之前的狀態(tài)。inN28資訊網(wǎng)——每日最新資訊28at.com

關(guān)于樂(lè)觀更新,我在日常開發(fā)中,經(jīng)常會(huì)用到。經(jīng)典的場(chǎng)景是點(diǎn)贊場(chǎng)景,用戶點(diǎn)贊后,立即更新 UI 為點(diǎn)贊成功,如果請(qǐng)求失敗后,再回滾 UI。inN28資訊網(wǎng)——每日最新資訊28at.com

使用 useOptimistic 后,其代碼如下:inN28資訊網(wǎng)——每日最新資訊28at.com

function LikeDemo() {  const [like, setLike] = useState(false);  // 定義樂(lè)觀更新的狀態(tài)  const [optimisticLike, setOptimisticLike] = useOptimistic(like);  const handleLike = async () => {    const targetLike = !like;    try {      // 請(qǐng)求之前,先把狀態(tài)更新到 optimisticLike      setOptimisticLike(targetLike);      await updateLike(like);      // 成功之后,更新最終狀態(tài)      setLike(targetLike);    } catch (e) {      console.error(e);    }  };  return (    <div>      <div onClick={handleLike}>{optimisticLike ? "收藏" : "未收藏"}</div>    </div>  );}

上面代碼看起來(lái)很簡(jiǎn)單,但是沒用,會(huì)報(bào)錯(cuò)。inN28資訊網(wǎng)——每日最新資訊28at.com

Warning: An optimistic state update occurred outside a transition or action. To fix, move the update to an action, or wrap with startTransition.

意思是 optimistic state 的更新,必須包裹在 startTransition 里面。inN28資訊網(wǎng)——每日最新資訊28at.com

根據(jù)告警再優(yōu)化下代碼。inN28資訊網(wǎng)——每日最新資訊28at.com

function LikeDemo() {  const [like, setLike] = useState(false);  const [pending, startTransition] = useTransition();  const [optimisticLike, setOptimisticLike] = useOptimistic(like);  const handleLike = () => {    const targetLike = !like;    startTransition(async () => {      try {        setOptimisticLike(targetLike);        await updateLike(like);        setLike(targetLike);      } catch (e) {        console.error(e);      }    });  };  return (    <div>      <div onClick={handleLike}>{optimisticLike ? "收藏" : "未收藏"}</div>    </div>  );}

增加了 startTransition 后,功能可以正常使用。inN28資訊網(wǎng)——每日最新資訊28at.com

為什么官方的示例代碼不用加 startTransition 呢?因?yàn)楣俜绞纠峭ㄟ^(guò) form 的 action 調(diào)用的,其默認(rèn)內(nèi)置了 startTransition。inN28資訊網(wǎng)——每日最新資訊28at.com

體驗(yàn)下來(lái),我覺得這個(gè) Hook,確實(shí)是沒啥用,我普通代碼實(shí)現(xiàn)個(gè)樂(lè)觀更新,更簡(jiǎn)單。inN28資訊網(wǎng)——每日最新資訊28at.com

const [like, setLike] = useState(false);  const handleLike = async () => {    try {      setLike((s) => !s);      await updateLike(like);    } catch (e) {      setLike((s) => !s);    }  };

上面我們介紹了 React 19 新增的幾個(gè) Hook,不知道大家看下來(lái)什么感受?說(shuō)說(shuō)我個(gè)人的感受。inN28資訊網(wǎng)——每日最新資訊28at.com

React 19 之前的 Hook,基本都是原子級(jí)別的,必要的,比如 useState、useEffect、useTransition等,沒有它就有些功能實(shí)現(xiàn)不了。inN28資訊網(wǎng)——每日最新資訊28at.com

但 React 19 新增的幾個(gè) Hook 明顯不是這樣的,而是更上層的封裝,并且和 form 耦合很嚴(yán)重。inN28資訊網(wǎng)——每日最新資訊28at.com

我覺得在實(shí)際業(yè)務(wù)開發(fā)中,幾乎不會(huì)用到上述 Hook。inN28資訊網(wǎng)——每日最新資訊28at.com

useFormStatus 獲取表單狀態(tài)

useFormStatus 是 React 19 新增的一個(gè) Hook,主要用來(lái)快捷讀取到最近的父級(jí) form 表單的數(shù)據(jù),其實(shí)就是類似 Context 的封裝。inN28資訊網(wǎng)——每日最新資訊28at.com

import { useFormStatus } from "react-dom";import action from './actions';function Submit() {  const status = useFormStatus();  return <button disabled={status.pending}>Submit</button>}export default function App() {  return (    <form action={action}>      <Submit />    </form>  );}
const { pending, data, method, action } = useFormStatus();

useFormStatus 能拿到父級(jí)最近的 form 的狀態(tài):inN28資訊網(wǎng)——每日最新資訊28at.com

  • pending:是否正在提交中。
  • data:表單正在提交的數(shù)據(jù),如果 form 沒有被提交,則為 null。
  • method:form 的 method 屬性,get 或 post。
  • action:form 的 action 屬性,如果 action 不是函數(shù),則為 null。

useFormStatus 使用場(chǎng)景較窄,絕大部分開發(fā)者不會(huì)用到。inN28資訊網(wǎng)——每日最新資訊28at.com

use

use 是 React 19 新增的一個(gè)特性,支持處理 Promise 和 Context。inN28資訊網(wǎng)——每日最新資訊28at.com

假如我們要實(shí)現(xiàn)這樣一個(gè)需求:請(qǐng)求接口數(shù)據(jù),請(qǐng)求過(guò)程中,顯示 loading,請(qǐng)求成功,展示數(shù)據(jù)。inN28資訊網(wǎng)——每日最新資訊28at.com

以前我們可能會(huì)這樣寫代碼。inN28資訊網(wǎng)——每日最新資訊28at.com

function ReactUseDemo() {  const [data, setData] = useState("");  const [loading, setLoading] = useState(false);  useEffect(() => {    setLoading(true);    getList()      .then((res) => {        setData(res);        setLoading(false);      })      .catch(() => {        setLoading(false);      });  }, []);  if (loading) return <div>Loading...</div>;  return <div>{data}</div>;}

通過(guò) use 我們可以把代碼改造成下面這樣。inN28資訊網(wǎng)——每日最新資訊28at.com

export default function ReactUseDemo() {  return (    <Suspense fallback={<div>Loading...</div>}>      <ChildCompont />    </Suspense>  );}function ChildCompont() {  const data = use(getData());  return <div>{data}</div>;}

use 接收一個(gè) Promise,會(huì)阻塞 render 繼續(xù)渲染,通常需要配套 Suspense 處理 loading 狀態(tài),需要配套 ErrorBoundary 來(lái)處理異常狀態(tài)。inN28資訊網(wǎng)——每日最新資訊28at.com

另外 use 也支持接收 Context,類似之前的 useContext,但比 useContext 更靈活,可以在條件語(yǔ)句和循環(huán)中使用。inN28資訊網(wǎng)——每日最新資訊28at.com

function MyPage() {  return (    <ThemeContext.Provider value="dark">      <Form />    </ThemeContext.Provider>  );}function Form() {  const theme = use(ThemeContext);  ......}

use 的使用有一些注意事項(xiàng)。inN28資訊網(wǎng)——每日最新資訊28at.com

  • 需要在組件或 Hook 內(nèi)部使用。
  • use 可以在條件語(yǔ)句(比如 if)或者循環(huán)(比如 for)里面調(diào)用。

ref

在之前,父組件傳遞 ref 給子組件,子組件如果要消費(fèi),則必須通過(guò) forwardRef 來(lái)消費(fèi)。inN28資訊網(wǎng)——每日最新資訊28at.com

function RefDemo() {  const inputRef = useRef(null);  const focusInput = () => {    inputRef.current.focus();  };  return (    <div>      <Input ref={inputRef} />      <button onClick={focusInput}>Focus</button>    </div>  );}const Input = forwardRef((props, ref) => {  return <input ref={ref} />;});

React 19 開始,不需要使用 forwardRef 了,ref 可以作為一個(gè)普通的 props 了。inN28資訊網(wǎng)——每日最新資訊28at.com

export const Input = ({ ref }) => {  return <input ref={ref} />;};

未來(lái)在某個(gè)版本會(huì)刪除掉 forwardRef。inN28資訊網(wǎng)——每日最新資訊28at.com

Context

在 React 19 之前,我們需要使用 Context.Provider,比如:inN28資訊網(wǎng)——每日最新資訊28at.com

import React, { createContext } from 'react'; const ThemeContext = createContext(''); function App({ children }) {  return (    <ThemeContext.Provider value="dark">      {children}    </ThemeContext.Provider>  );}

在 React 19 中,我們可以使用 Context來(lái)代替 Context.Provider了。inN28資訊網(wǎng)——每日最新資訊28at.com

function App({ children }) {  return (    <ThemeContext value="dark">      {children}    </ThemeContext>  );}

未來(lái)在某個(gè)版本會(huì)刪除掉 Context.Provider。inN28資訊網(wǎng)——每日最新資訊28at.com

ref 支持返回 cleanup 函數(shù)

ref 支持返回一個(gè) cleanup 函數(shù),在組件卸載時(shí)會(huì)調(diào)用該函數(shù)。inN28資訊網(wǎng)——每日最新資訊28at.com

<input  ref={(ref) => {    // ref created    // NEW: return a cleanup function to reset    // the ref when element is removed from DOM.    return () => {      // ref cleanup    };  }}/>

useDeferredValue 增加了 initialValue 參數(shù)

useDeferredValue 現(xiàn)在增加了第二個(gè)參數(shù) initialValue,指定初始化值。inN28資訊網(wǎng)——每日最新資訊28at.com

const value = useDeferredValue(deferredValue, initialValue);

支持 Document Metadata

在之前,如果我們希望動(dòng)態(tài)的在組件中指定 meta、title、link等文檔屬性,我們可能會(huì)這樣做:inN28資訊網(wǎng)——每日最新資訊28at.com

  • 在 useEffect 中,通過(guò) JS 手動(dòng)創(chuàng)建
  • 使用 react-helmet 這類三方庫(kù)

在 React 19 中,原生支持了這三個(gè)文檔屬性,支持在組件中設(shè)置。inN28資訊網(wǎng)——每日最新資訊28at.com

在渲染過(guò)程中,React 發(fā)現(xiàn)這三種標(biāo)簽,會(huì)自動(dòng)提升到  上。inN28資訊網(wǎng)——每日最新資訊28at.com

function BlogPost({post}) {  return (    <div>      <meta name="author" content="Josh" />      <link rel="author"  />      <meta name="keywords" content={post.keywords} />    </div>  );}

其它更多特性

  • Server Components 和 Server Actions 將成為穩(wěn)定特性
  • 更多外聯(lián)樣式表能力支持:比如支持通過(guò) precedence指定樣式表的優(yōu)先級(jí),同樣優(yōu)先級(jí)的樣式表會(huì)被放到一起
  • 更多 script 標(biāo)簽?zāi)芰χС?/li>
  • 支持預(yù)加載資源

參考資料inN28資訊網(wǎng)——每日最新資訊28at.com

[1]React 18 全覽: https://github.com/brickspert/blog/issues/48。inN28資訊網(wǎng)——每日最新資訊28at.com

[2]https://codesandbox.io/p/sandbox/react19-demo-lmygpv: https://codesandbox.io/p/sandbox/react19-demo-lmygpv。inN28資訊網(wǎng)——每日最新資訊28at.com

[3]useQuery: https://tanstack.com/query/latest/docs/framework/react/overview。inN28資訊網(wǎng)——每日最新資訊28at.com

[4]useRequest: https://ahooks.js.org/hooks/use-request/index。inN28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-93707-0.htmlReact 19 全覽,新特性進(jìn)行一次深度的體驗(yàn)學(xué)習(xí)

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 轉(zhuǎn)轉(zhuǎn)回收持久層的架構(gòu)演進(jìn)

下一篇: 淺析Spring中Async注解底層異步線程池原理

標(biāo)簽:
  • 熱門焦點(diǎn)
Top