@reach/auto-id
Advanced tools
Comparing version 0.5.3 to 0.6.1
@@ -1,7 +0,46 @@ | ||
import { useState, useEffect } from "react"; // Could use UUID but if we hit 9,007,199,254,740,991 unique components over | ||
// the lifetime of the app before it gets reloaded, I mean ... come on. | ||
// I don't even know what xillion that is. | ||
// /me googles | ||
// Oh duh, quadrillion. Nine quadrillion components. I think we're okay. | ||
/* | ||
* Let's see if we can make sense of why this hook exists and its | ||
* implementation. | ||
* | ||
* Some background: | ||
* 1. Accessibiliy APIs rely heavily on element IDs | ||
* 2. Requiring developers to put IDs on every element in Reach UI is both | ||
* cumbersome and error-prone | ||
* 3. With a component model, we can generate IDs for them! | ||
* | ||
* Solution 1: Generate random IDs. | ||
* | ||
* This works great as long as you don't server render your app. When React (in | ||
* the client) tries to reuse the markup from the server, the IDs won't match | ||
* and React will then recreate the entire DOM tree. | ||
* | ||
* Solution 2: Increment an integer | ||
* | ||
* This sounds great. Since we're rendering the exact same tree on the server | ||
* and client, we can increment a counter and get a deterministic result between | ||
* client and server. Also, JS integers can go up to nine-quadrillion. I'm | ||
* pretty sure the tab will be closed before an app never needs | ||
* 10 quadrillion IDs! | ||
* | ||
* Problem solved, right? | ||
* | ||
* Ah, but there's a catch! React's concurrent rendering makes this approach | ||
* non-deterministic. While the client and server will end up with the same | ||
* elements in the end, depending on suspense boundaries (and possibly some user | ||
* input during the initial render) the incrementing integers won't always match | ||
* up. | ||
* | ||
* Solution 3: Don't use IDs at all on the server; patch after first render. | ||
* | ||
* What we've done here is solution 2 with some tricks. With this approach, the | ||
* ID returned is an empty string on the first render. This way the server and | ||
* client have the same markup no matter how wild the concurrent rendering may | ||
* have gotten. | ||
* | ||
* After the render, we patch up the components with an incremented ID. It | ||
* doesn't have to be incremented, though; we could do something random, but | ||
* incrementing a number is probably the cheapest thing we can do. | ||
*/ | ||
import { useState, useEffect, useLayoutEffect } from "react"; | ||
var serverHandoffComplete = false; | ||
var id = 0; | ||
@@ -13,11 +52,36 @@ | ||
export var useId = function useId() { | ||
var _useState = useState(null), | ||
export var useId = function useId(fallback) { | ||
/* | ||
* If this instance isn't part of the initial render, we don't have to do the | ||
* double render/patch-up dance. We can just generate the ID and return it. | ||
*/ | ||
var initialId = fallback || (serverHandoffComplete ? genId() : null); | ||
var _useState = useState(initialId), | ||
id = _useState[0], | ||
setId = _useState[1]; | ||
useLayoutEffect(function () { | ||
if (id === null) { | ||
/* | ||
* Patch the ID after render. We do this in `useLayoutEffect` to avoid any | ||
* rendering flicker, though it'll make the first render slower (unlikely | ||
* to matter, but you're welcome to measure your app and let us know if | ||
* it's a problem). | ||
*/ | ||
setId(genId()); | ||
} // eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
useEffect(function () { | ||
return setId(genId()); | ||
if (serverHandoffComplete === false) { | ||
/* | ||
* Flag all future uses of `useId` to skip the update dance. This is in | ||
* `useEffect` because it goes after `useLayoutEffect`, ensuring we don't | ||
* accidentally bail out of the patch-up dance prematurely. | ||
*/ | ||
serverHandoffComplete = true; | ||
} | ||
}, []); | ||
return id; | ||
}; |
@@ -10,2 +10,2 @@ /** | ||
*/ | ||
export const useId: () => number; | ||
export const useId: (hasFallback?: string) => number; |
80
index.js
@@ -8,7 +8,46 @@ "use strict"; | ||
// Could use UUID but if we hit 9,007,199,254,740,991 unique components over | ||
// the lifetime of the app before it gets reloaded, I mean ... come on. | ||
// I don't even know what xillion that is. | ||
// /me googles | ||
// Oh duh, quadrillion. Nine quadrillion components. I think we're okay. | ||
/* | ||
* Let's see if we can make sense of why this hook exists and its | ||
* implementation. | ||
* | ||
* Some background: | ||
* 1. Accessibiliy APIs rely heavily on element IDs | ||
* 2. Requiring developers to put IDs on every element in Reach UI is both | ||
* cumbersome and error-prone | ||
* 3. With a component model, we can generate IDs for them! | ||
* | ||
* Solution 1: Generate random IDs. | ||
* | ||
* This works great as long as you don't server render your app. When React (in | ||
* the client) tries to reuse the markup from the server, the IDs won't match | ||
* and React will then recreate the entire DOM tree. | ||
* | ||
* Solution 2: Increment an integer | ||
* | ||
* This sounds great. Since we're rendering the exact same tree on the server | ||
* and client, we can increment a counter and get a deterministic result between | ||
* client and server. Also, JS integers can go up to nine-quadrillion. I'm | ||
* pretty sure the tab will be closed before an app never needs | ||
* 10 quadrillion IDs! | ||
* | ||
* Problem solved, right? | ||
* | ||
* Ah, but there's a catch! React's concurrent rendering makes this approach | ||
* non-deterministic. While the client and server will end up with the same | ||
* elements in the end, depending on suspense boundaries (and possibly some user | ||
* input during the initial render) the incrementing integers won't always match | ||
* up. | ||
* | ||
* Solution 3: Don't use IDs at all on the server; patch after first render. | ||
* | ||
* What we've done here is solution 2 with some tricks. With this approach, the | ||
* ID returned is an empty string on the first render. This way the server and | ||
* client have the same markup no matter how wild the concurrent rendering may | ||
* have gotten. | ||
* | ||
* After the render, we patch up the components with an incremented ID. It | ||
* doesn't have to be incremented, though; we could do something random, but | ||
* incrementing a number is probably the cheapest thing we can do. | ||
*/ | ||
var serverHandoffComplete = false; | ||
var id = 0; | ||
@@ -20,9 +59,34 @@ | ||
var useId = function useId() { | ||
var _useState = (0, _react.useState)(null), | ||
var useId = function useId(fallback) { | ||
/* | ||
* If this instance isn't part of the initial render, we don't have to do the | ||
* double render/patch-up dance. We can just generate the ID and return it. | ||
*/ | ||
var initialId = fallback || (serverHandoffComplete ? genId() : null); | ||
var _useState = (0, _react.useState)(initialId), | ||
id = _useState[0], | ||
setId = _useState[1]; | ||
(0, _react.useLayoutEffect)(function () { | ||
if (id === null) { | ||
/* | ||
* Patch the ID after render. We do this in `useLayoutEffect` to avoid any | ||
* rendering flicker, though it'll make the first render slower (unlikely | ||
* to matter, but you're welcome to measure your app and let us know if | ||
* it's a problem). | ||
*/ | ||
setId(genId()); | ||
} // eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
(0, _react.useEffect)(function () { | ||
return setId(genId()); | ||
if (serverHandoffComplete === false) { | ||
/* | ||
* Flag all future uses of `useId` to skip the update dance. This is in | ||
* `useEffect` because it goes after `useLayoutEffect`, ensuring we don't | ||
* accidentally bail out of the patch-up dance prematurely. | ||
*/ | ||
serverHandoffComplete = true; | ||
} | ||
}, []); | ||
@@ -29,0 +93,0 @@ return id; |
{ | ||
"name": "@reach/auto-id", | ||
"version": "0.5.3", | ||
"version": "0.6.1", | ||
"description": "Autogenerate IDs to facilitate WAI-ARIA and server rendering.", | ||
@@ -23,3 +23,3 @@ "main": "index.js", | ||
], | ||
"gitHead": "29e599938054fd0601f347f66d8671e690ecf879" | ||
"gitHead": "c1e249448a3672ccc65698218f0f38ef9814ab90" | ||
} |
@@ -1,15 +0,84 @@ | ||
import { useState, useEffect } from "react"; | ||
/* | ||
* Let's see if we can make sense of why this hook exists and its | ||
* implementation. | ||
* | ||
* Some background: | ||
* 1. Accessibiliy APIs rely heavily on element IDs | ||
* 2. Requiring developers to put IDs on every element in Reach UI is both | ||
* cumbersome and error-prone | ||
* 3. With a component model, we can generate IDs for them! | ||
* | ||
* Solution 1: Generate random IDs. | ||
* | ||
* This works great as long as you don't server render your app. When React (in | ||
* the client) tries to reuse the markup from the server, the IDs won't match | ||
* and React will then recreate the entire DOM tree. | ||
* | ||
* Solution 2: Increment an integer | ||
* | ||
* This sounds great. Since we're rendering the exact same tree on the server | ||
* and client, we can increment a counter and get a deterministic result between | ||
* client and server. Also, JS integers can go up to nine-quadrillion. I'm | ||
* pretty sure the tab will be closed before an app never needs | ||
* 10 quadrillion IDs! | ||
* | ||
* Problem solved, right? | ||
* | ||
* Ah, but there's a catch! React's concurrent rendering makes this approach | ||
* non-deterministic. While the client and server will end up with the same | ||
* elements in the end, depending on suspense boundaries (and possibly some user | ||
* input during the initial render) the incrementing integers won't always match | ||
* up. | ||
* | ||
* Solution 3: Don't use IDs at all on the server; patch after first render. | ||
* | ||
* What we've done here is solution 2 with some tricks. With this approach, the | ||
* ID returned is an empty string on the first render. This way the server and | ||
* client have the same markup no matter how wild the concurrent rendering may | ||
* have gotten. | ||
* | ||
* After the render, we patch up the components with an incremented ID. It | ||
* doesn't have to be incremented, though; we could do something random, but | ||
* incrementing a number is probably the cheapest thing we can do. | ||
*/ | ||
// Could use UUID but if we hit 9,007,199,254,740,991 unique components over | ||
// the lifetime of the app before it gets reloaded, I mean ... come on. | ||
// I don't even know what xillion that is. | ||
// /me googles | ||
// Oh duh, quadrillion. Nine quadrillion components. I think we're okay. | ||
import { useState, useEffect, useLayoutEffect } from "react"; | ||
let serverHandoffComplete = false; | ||
let id = 0; | ||
const genId = () => ++id; | ||
export const useId = () => { | ||
const [id, setId] = useState(null); | ||
useEffect(() => setId(genId()), []); | ||
export const useId = fallback => { | ||
/* | ||
* If this instance isn't part of the initial render, we don't have to do the | ||
* double render/patch-up dance. We can just generate the ID and return it. | ||
*/ | ||
const initialId = fallback || (serverHandoffComplete ? genId() : null); | ||
const [id, setId] = useState(initialId); | ||
useLayoutEffect(() => { | ||
if (id === null) { | ||
/* | ||
* Patch the ID after render. We do this in `useLayoutEffect` to avoid any | ||
* rendering flicker, though it'll make the first render slower (unlikely | ||
* to matter, but you're welcome to measure your app and let us know if | ||
* it's a problem). | ||
*/ | ||
setId(genId()); | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
useEffect(() => { | ||
if (serverHandoffComplete === false) { | ||
/* | ||
* Flag all future uses of `useId` to skip the update dance. This is in | ||
* `useEffect` because it goes after `useLayoutEffect`, ensuring we don't | ||
* accidentally bail out of the patch-up dance prematurely. | ||
*/ | ||
serverHandoffComplete = true; | ||
} | ||
}, []); | ||
return id; | ||
}; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
12597
7
283
1