一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
一、客户端渲染
在这之前,渲染组件、元素中的key值,用的都是for循环中的index、后端接口返回的id值、随机数。
// App.tsx
const id = Math.random();
export default function App() {
return <div id={id}>Hello World!</div>
}
如果应用是客户端渲染,id是稳定的,这样使用App组件是没有问题(注意:使用随机数,会重新渲染该组件,一般用于表单弹窗、需要重新渲染的组件)。
二、服务端渲染
但如果应用是服务端渲染,那么App组件会经历:
-
React在服务端渲染,生成随机id(假设为0.1234);
-
Hello World!
作为HTML传递给客户端,作为首屏内容;
-
React在客户端渲染,生成随机id(假设为0.5678),客户端、服务端生成的id就不匹配;
由于ssr 场景下,客户端、服务端生成的id不匹配!官方推出新Hook——useId来解决,每个 id 代表该组件在组件树中的层级结构。
// App.tsx
const { useId } from "react";
const id = useId();
export default function App() {
return <div id={id}>Hello World!</div>
}
三、useId的原理
useId为何能做到客户端和服务端渲染时,id能保持一致呢?关键在于组件树的层级结构是不变的,那么「层级」本身就能作为服务端、客户端之间不变的标识。
const { useId } from "react";
function () {
// id为"2-1"
const id = useId();
return <div id={id}>B</div>;
}
在useId的实际实现中,层级被表示为「32进制」的数。之所以选择「32进制」,是因为选择尽可能大的进制会让生成的字符串尽可能紧凑。
具体的useId层级算法可以参考这个链接:github.com/facebook/re…