湖北长安建设集团股份有限公司网站,赤壁网站定制,外包加工网是正规的吗,全国加盟网站建设React 中有一个 useId hook#xff0c;可以生成一个唯一 ID#xff0c;这个有什么用处呢#xff0c;用个 UUID 是不是可以替代呢#xff1f;如果我们只考虑客户端#xff0c;那么生成唯一 Id 的方法比较简单#xff0c;我们在 State 中保存一个计数器就好#xff0c;但是…React 中有一个 useId hook可以生成一个唯一 ID这个有什么用处呢用个 UUID 是不是可以替代呢如果我们只考虑客户端那么生成唯一 Id 的方法比较简单我们在 State 中保存一个计数器就好但是 React 需要支持服务端渲染需要确保服务器生成的内容与客户端保持一致。客户端和服务器端是完全不同的环境通过简单的计数器无法确保两端的一致。我们看下面这个例子例子中要将 label 和 输入框进行关联可以 useId 这个 hook 来实现。通过简单的计数器无法实现
import { useId } from react;export default function Form() {const id useId();return (formlabel htmlFor{id -firstName}First Name:/labelinput id{id -firstName} typetext /hr /label htmlFor{id -lastName}Last Name:/labelinput id{id -lastName} typetext //form);
}React 是通过 dom tree 的位置来实现的不同层有不同的前缀如下
divdiv id1div id101 //divdiv id10 /
/div下面代码 React 源码中的 Id 生成算法通过位置进行移位并对索引进行相加。
export function pushTreeId(workInProgress: Fiber,totalChildren: number,index: number,
) {warnIfNotHydrating();idStack[idStackIndex] treeContextId;idStack[idStackIndex] treeContextOverflow;idStack[idStackIndex] treeContextProvider;treeContextProvider workInProgress;const baseIdWithLeadingBit treeContextId;const baseOverflow treeContextOverflow;// The leftmost 1 marks the end of the sequence, non-inclusive. Its not part// of the id; we use it to account for leading 0s.const baseLength getBitLength(baseIdWithLeadingBit) - 1;const baseId baseIdWithLeadingBit ~(1 baseLength);const slot index 1;const length getBitLength(totalChildren) baseLength;// 30 is the max length we can store without overflowing, taking into// consideration the leading 1 we use to mark the end of the sequence.if (length 30) {// We overflowed the bitwise-safe range. Fall back to slower algorithm.// This branch assumes the length of the base id is greater than 5; it wont// work for smaller ids, because you need 5 bits per character.//// We encode the id in multiple steps: first the base id, then the// remaining digits.//// Each 5 bit sequence corresponds to a single base 32 character. So for// example, if the current id is 23 bits long, we can convert 20 of those// bits into a string of 4 characters, with 3 bits left over.//// First calculate how many bits in the base id represent a complete// sequence of characters.const numberOfOverflowBits baseLength - (baseLength % 5);// Then create a bitmask that selects only those bits.const newOverflowBits (1 numberOfOverflowBits) - 1;// Select the bits, and convert them to a base 32 string.const newOverflow (baseId newOverflowBits).toString(32);// Now we can remove those bits from the base id.const restOfBaseId baseId numberOfOverflowBits;const restOfBaseLength baseLength - numberOfOverflowBits;// Finally, encode the rest of the bits using the normal algorithm. Because// we made more room, this time it wont overflow.const restOfLength getBitLength(totalChildren) restOfBaseLength;const restOfNewBits slot restOfBaseLength;const id restOfNewBits | restOfBaseId;const overflow newOverflow baseOverflow;treeContextId (1 restOfLength) | id;treeContextOverflow overflow;} else {// Normal pathconst newBits slot baseLength;const id newBits | baseId;const overflow baseOverflow;treeContextId (1 length) | id;treeContextOverflow overflow;}
}这个Id 算法只有服务器渲染才需要如果只是客户端渲染无需这么复杂的计算React 也做了这样的处理代码如下客户端渲染直接使用全局计数器。
总结
useId 这个 Hook是为了服务端渲染的需求才有的客户端渲染无需这种复杂计算。不同层使用不同的前缀通过移位进行区分。