-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create
useWarningLogger
hook (#2213)
- Loading branch information
Showing
8 changed files
with
88 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@itwin/itwinui-react': patch | ||
--- | ||
|
||
Dev-only warnings have been improved so that they are correctly shown for every individual instance of a component. Additionally, these warnings are now logged using `console.error`, which results in a better stack trace. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
packages/itwinui-react/src/utils/hooks/useWarningLogger.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Bentley Systems, Incorporated. All rights reserved. | ||
* See LICENSE.md in the project root for license terms and full copyright notice. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as React from 'react'; | ||
import { isUnitTest } from '../functions/dev.js'; | ||
|
||
const _React = React as any; | ||
const ReactInternals = | ||
_React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; | ||
|
||
/** | ||
* Returns a function that can be used to log one-time warnings in dev environments. | ||
* | ||
* **Note**: The actual log call should be wrapped in a check against `process.env.NODE_ENV === 'development'` | ||
* to ensure that it is removed from the production build output (by SWC). | ||
* Read more about the [`NODE_ENV` convention](https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production). | ||
* | ||
* @example | ||
* const logWarning = useWarningLogger(); | ||
* | ||
* if (process.env.NODE_ENV === 'development') { | ||
* logWarning("please don't use this") | ||
* } | ||
*/ | ||
export const useWarningLogger = | ||
process.env.NODE_ENV === 'development' && !isUnitTest | ||
? function () { | ||
const loggedRef = React.useRef(false); | ||
const timeoutRef = React.useRef<number | null>(null); | ||
|
||
// https://stackoverflow.com/a/71685253 | ||
const stack = | ||
ReactInternals?.ReactDebugCurrentFrame?.getCurrentStack?.(); | ||
|
||
// Second line in the stack is the component name. | ||
const componentName = stack?.trim().split('\n')[1]?.trim(); | ||
|
||
const prefix = componentName | ||
? `Warning (${componentName}):` | ||
: 'Warning:'; | ||
|
||
const logWarning = React.useCallback( | ||
(message: string) => { | ||
// Using setTimeout to delay execution until after rendering is complete. | ||
timeoutRef.current = window.setTimeout(() => { | ||
if (!loggedRef.current) { | ||
console.error(prefix, message); | ||
loggedRef.current = true; | ||
} | ||
}); | ||
}, | ||
[prefix], | ||
); | ||
|
||
React.useEffect(() => { | ||
// Clearing timeout on unmount to avoid double execution in StrictMode. | ||
// The warning should be logged only once per component instance. | ||
return () => { | ||
if (timeoutRef.current) { | ||
window.clearTimeout(timeoutRef.current); | ||
} | ||
}; | ||
}, []); | ||
|
||
return logWarning; | ||
} | ||
: () => () => {}; |