Skip to content

Commit

Permalink
defend against useId call outside of rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
gnoff committed Mar 28, 2022
1 parent 36cea2f commit 0cfea27
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 21 deletions.
8 changes: 4 additions & 4 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Expand Up @@ -534,8 +534,8 @@ describe('ReactFlight', () => {
});
expect(ReactNoop).toMatchRenderedOutput(
<>
<div prop=":$:F1" />
<div prop=":$:F2" />
<div prop=":F1:" />
<div prop=":F2:" />
</>,
);
});
Expand All @@ -558,8 +558,8 @@ describe('ReactFlight', () => {
});
expect(ReactNoop).toMatchRenderedOutput(
<>
<div prop=":foo:F1" />
<div prop=":foo:F2" />
<div prop=":fooF1:" />
<div prop=":fooF2:" />
</>,
);
});
Expand Down
28 changes: 12 additions & 16 deletions packages/react-server/src/ReactFlightHooks.js
Expand Up @@ -13,20 +13,14 @@ import type {ReactServerContext} from 'shared/ReactTypes';
import {REACT_SERVER_CONTEXT_TYPE} from 'shared/ReactSymbols';
import {readContext as readContextImpl} from './ReactFlightNewContext';

let currentIndentifierPrefix = '$';
let currentIndentifierCount = 0;
let currentRequest = null;

export function prepareToUseHooksForRequest(request: Request) {
if (request.identifierPrefix) {
currentIndentifierPrefix = request.identifierPrefix;
}
currentIndentifierCount = request.identifierCount;
currentRequest = request;
}

export function resetHooksForRequest(request: Request) {
currentIndentifierPrefix = '$';
request.identifierCount = currentIndentifierCount;
currentIndentifierCount = 0;
export function resetHooksForRequest() {
currentRequest = null;
}

function readContext<T>(context: ReactServerContext<T>): T {
Expand Down Expand Up @@ -110,10 +104,12 @@ export function getCurrentCache() {
}

function useId(): string {
return (
':' +
currentIndentifierPrefix +
':F' +
(currentIndentifierCount++).toString(32)
);
if (currentRequest === null) {
throw new Error('useId can only be used while React is rendering.');
}
const prefix = currentRequest.identifierPrefix
? currentRequest.identifierPrefix
: '';
const id = currentRequest.identifierCount++;
return ':' + prefix + 'F' + id.toString(32) + ':';
}
2 changes: 1 addition & 1 deletion packages/react-server/src/ReactFlightServer.js
Expand Up @@ -851,7 +851,7 @@ function performWork(request: Request): void {
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
setCurrentCache(prevCache);
resetHooksForRequest(request);
resetHooksForRequest();
}
}

Expand Down

0 comments on commit 0cfea27

Please sign in to comment.