为了生成唯一的id,React18特地引入了一个新的Hook:useId
时间:2023-03-28 14:38:46
HTML
大家好,我是Kason。看看下面这个组件有什么问题://App.tsxconstid=Math.random();exportdefaultfunctionApp(){returnHello
}如果应用是CSR(客户端渲染),id稳定,App组件没有问题。但是如果应用是SSR(服务端渲染),那么App.tsx会经过:React在服务端渲染生成一个随机id(假设为0.1234),这一步叫做dehydrate(脱水)
Hello 作为HTML传递给客户端,React将其渲染在客户端作为首屏内容生成一个随机id(假设为0.6789)。此步骤称为水合物(注水)。客户端和服务器生成的id不匹配!实际上,服务端和客户端不能简单的生成一个稳定唯一的id是一个长期存在的问题。早在15年前,就有人提出了这个问题:Generatingrandom/uniqueattributesserver-sidethatdon'tbreakclient-sidemounting直到最近,React18推出了官方的Hook——useId,来解决上述问题。他的用法很简单:functionCheckbox(){//生成唯一稳定的idconstid=useId();return(<>
你喜欢React吗?>);;用法虽然简单,但背后的原理却很有趣——每个id代表了组件在组件树中的层级结构。这篇文章让我们了解useId的原理。欢迎加入人类优质前端框架群。随着React18的到来,一切都变了。虽然这个问题一直存在,但是一直可以用自增的全局计数变量作为id。考虑以下示例://globalcommoncountingvariableletglobalIdIndex=0;exportdefaultfunctionApp(){constid=useState(()=>globalIdIndex++);returnHello }只要React在服务端和客户端运行在同一个进程,那么双端生成的id就是对应的。然而,随着ReactFizz(React的新服务器端流式渲染器)的到来,渲染顺序不再是必需的。例如,有一个名为SelectiveHydration的功能,它可以根据用户交互改变水合物的顺序。下图左边部分水合时,用户点击右下部分:React此时会优先水合右下部分:SelectiveHydration更详细的解释见:NewSuspenseSSRArchitectureinReact18如果应用使用自增全局count变量作为id,那么显然先水合的组件id会更小,所以id不稳定。那么,有没有迹象表明服务器和客户端都稳定了呢?答案是:组件的层次结构。useId的原理假设应用的组件树如下图所示:无论谁先水化B或C,它们的层级结构都保持不变,因此层级本身可以作为服务端和服务端之间的不变标识客户端。例如,B可以使用2-1作为id,C可以使用2-2作为id:functionB(){//idis"2-1"constid=useId();return
B ;}其实需要考虑两个要素:1.同一个组件使用多个id像这样:functionB(){constid0=useId();constid1=useId();return(