关于react.js:React中的useId

4次阅读

共计 1385 个字符,预计需要花费 4 分钟才能阅读完成。

简介

useId 是新增的用于生成 惟一 ID 值 的 hook 钩子,次要用于 客户端和服务器端 应用,同时防止 dehydrate 过程中数据不匹配的问题。

它次要用于与须要惟一 ID 的可拜访性 API 集成的组件库。这解决了 React 17 及更低版本中曾经存在的问题,但在 React 18 中更为重要,因为新的流式服务器渲染器如何无序交付 HTML。

然而,不倡议用于 List 中作为 key 应用,列表中的惟一 key 应该应用 List 中的数据。

问题

React 渲染有客户端渲染(CSR)和服务端渲染(SSR)。

假如有如下代码片段:

// App.tsx
const id = Math.random();

export default function App() {return <div id={id}>Hello</div>
}

如果利用是 CSR(客户端渲染),id 是稳固的,App 组件没有问题。

但如果利用是 SSR(服务端渲染),那么 App.tsx 会分为以下几步:

  1. React 在服务端渲染,生成随机 id(假如为 0.1234),这一步叫 dehydrate(脱水);
  2. <div id=”0.12345″>Hello</div> 作为 HTML 传递给客户端,作为首屏内容;
  3. React 在客户端渲染,生成随机 id(假如为 0.6789),这一步叫 hydrate(注水)。

客户端、服务端生成的 id 不匹配!

原始解决形式:

// 全局通用的计数变量
let globalIdIndex = 0;


export default function App() {const id = useState(() => globalIdIndex++);
  return <div id={id}>Hello</div>
}

只有 React 在服务端、客户端的运行流程统一,那么双端产生的 id 就是对应的。

然而,随着 React Fizz(React 新的服务端流式渲染器)的到来,渲染程序不再肯定。

比方,有个个性叫 Selective Hydration,能够依据用户交互扭转 hydrate 的程序。

当下图左侧局部在 hydrate 时,用户点击了右下角局部:

此时 React 会优先对右下角局部 hydrate:

因而,自增的全局计数变量作为 id,不再精确!!

那么,有没有什么是服务端、客户端都稳固的标记呢?

答案是:组件的层次结构。

useId 的原理

假如利用的组件树如下图:

不论 B 和 C 谁先 hydrate,他们的层级构造是不变的,所以「层级」自身就能作为服务端、客户端之间不变的标识。

比方 B 能够应用 2 - 1 作为 id,C 应用 2 - 2 作为 id:

function B() {
  // id 为 "2-1"
  const id = useId();
  return <div id={id}>B</div>;
}

如何在一个组件中应用多个 useId()?
react 举荐应用雷同的 id+ 后缀:

function NameFields() {const id = useId();
  return (
    <div>
      <label htmlFor={id + '-firstName'}>First Name</label>
      <div>
        <input id={id + '-firstName'} type="text" />
      </div>
      <label htmlFor={id + '-lastName'}>Last Name</label>
      <div>
        <input id={id + '-lastName'} type="text" />
      </div>
    </div>
  );
}
正文完
 0