1. /** @flow */
    
  2. 
    
  3. import * as React from 'react';
    
  4. import {Fragment, useEffect, useRef, useState} from 'react';
    
  5. 
    
  6. // $FlowFixMe[missing-local-annot]
    
  7. function WarnDuringRender({children = null}) {
    
  8.   console.warn('This warning fires during every render');
    
  9.   return children;
    
  10. }
    
  11. 
    
  12. // $FlowFixMe[missing-local-annot]
    
  13. function WarnOnMount({children = null}) {
    
  14.   useEffect(() => {
    
  15.     console.warn('This warning fires on initial mount only');
    
  16.   }, []);
    
  17.   return children;
    
  18. }
    
  19. 
    
  20. // $FlowFixMe[missing-local-annot]
    
  21. function WarnOnUpdate({children = null}) {
    
  22.   const didMountRef = useRef(false);
    
  23.   useEffect(() => {
    
  24.     if (didMountRef.current) {
    
  25.       console.warn('This warning fires on every update');
    
  26.     } else {
    
  27.       didMountRef.current = true;
    
  28.     }
    
  29.   });
    
  30.   return children;
    
  31. }
    
  32. 
    
  33. // $FlowFixMe[missing-local-annot]
    
  34. function WarnOnUnmount({children = null}) {
    
  35.   useEffect(() => {
    
  36.     return () => {
    
  37.       console.warn('This warning fires on unmount');
    
  38.     };
    
  39.   }, []);
    
  40.   return children;
    
  41. }
    
  42. 
    
  43. // $FlowFixMe[missing-local-annot]
    
  44. function ErrorDuringRender({children = null}) {
    
  45.   console.error('This error fires during every render');
    
  46.   return children;
    
  47. }
    
  48. 
    
  49. // $FlowFixMe[missing-local-annot]
    
  50. function ErrorOnMount({children = null}) {
    
  51.   useEffect(() => {
    
  52.     console.error('This error fires on initial mount only');
    
  53.   }, []);
    
  54.   return children;
    
  55. }
    
  56. 
    
  57. // $FlowFixMe[missing-local-annot]
    
  58. function ErrorOnUpdate({children = null}) {
    
  59.   const didMountRef = useRef(false);
    
  60.   useEffect(() => {
    
  61.     if (didMountRef.current) {
    
  62.       console.error('This error fires on every update');
    
  63.     } else {
    
  64.       didMountRef.current = true;
    
  65.     }
    
  66.   });
    
  67.   return children;
    
  68. }
    
  69. 
    
  70. // $FlowFixMe[missing-local-annot]
    
  71. function ErrorOnUnmount({children = null}) {
    
  72.   useEffect(() => {
    
  73.     return () => {
    
  74.       console.error('This error fires on unmount');
    
  75.     };
    
  76.   }, []);
    
  77.   return children;
    
  78. }
    
  79. 
    
  80. // $FlowFixMe[missing-local-annot]
    
  81. function ErrorAndWarningDuringRender({children = null}) {
    
  82.   console.warn('This warning fires during every render');
    
  83.   console.error('This error fires during every render');
    
  84.   return children;
    
  85. }
    
  86. 
    
  87. // $FlowFixMe[missing-local-annot]
    
  88. function ErrorAndWarningOnMount({children = null}) {
    
  89.   useEffect(() => {
    
  90.     console.warn('This warning fires on initial mount only');
    
  91.     console.error('This error fires on initial mount only');
    
  92.   }, []);
    
  93.   return children;
    
  94. }
    
  95. 
    
  96. // $FlowFixMe[missing-local-annot]
    
  97. function ErrorAndWarningOnUpdate({children = null}) {
    
  98.   const didMountRef = useRef(false);
    
  99.   useEffect(() => {
    
  100.     if (didMountRef.current) {
    
  101.       console.warn('This warning fires on every update');
    
  102.       console.error('This error fires on every update');
    
  103.     } else {
    
  104.       didMountRef.current = true;
    
  105.     }
    
  106.   });
    
  107.   return children;
    
  108. }
    
  109. 
    
  110. // $FlowFixMe[missing-local-annot]
    
  111. function ErrorAndWarningOnUnmount({children = null}) {
    
  112.   useEffect(() => {
    
  113.     return () => {
    
  114.       console.warn('This warning fires on unmount');
    
  115.       console.error('This error fires on unmount');
    
  116.     };
    
  117.   }, []);
    
  118.   return children;
    
  119. }
    
  120. 
    
  121. // $FlowFixMe[missing-local-annot]
    
  122. function ReallyLongErrorMessageThatWillCauseTextToBeTruncated({
    
  123.   children = null,
    
  124. }) {
    
  125.   console.error(
    
  126.     'This error is a really long error message that should cause the text to be truncated in DevTools',
    
  127.   );
    
  128.   return children;
    
  129. }
    
  130. 
    
  131. // $FlowFixMe[missing-local-annot]
    
  132. function ErrorWithMultipleArgs({children = null}) {
    
  133.   console.error('This error', 'passes console', 4, 'arguments');
    
  134.   return children;
    
  135. }
    
  136. 
    
  137. // $FlowFixMe[missing-local-annot]
    
  138. function ErrorWithStringSubstitutions({children = null}) {
    
  139.   console.error('This error uses "%s" substitutions', 'string');
    
  140.   return children;
    
  141. }
    
  142. 
    
  143. // $FlowFixMe[missing-local-annot]
    
  144. function ReactErrorOnHostComponent({children = null}) {
    
  145.   return <div data-camelCasedAttribute="should-lower-case">{children}</div>;
    
  146. }
    
  147. 
    
  148. // $FlowFixMe[missing-local-annot]
    
  149. function DuplicateWarningsAndErrors({children = null}) {
    
  150.   console.warn('this warning is logged twice per render');
    
  151.   console.warn('this warning is logged twice per render');
    
  152.   console.error('this error is logged twice per render');
    
  153.   console.error('this error is logged twice per render');
    
  154.   return <div data-camelCasedAttribute="should-lower-case">{children}</div>;
    
  155. }
    
  156. 
    
  157. // $FlowFixMe[missing-local-annot]
    
  158. function MultipleWarningsAndErrors({children = null}) {
    
  159.   console.warn('this is the first warning logged');
    
  160.   console.warn('this is the second warning logged');
    
  161.   console.error('this is the first error logged');
    
  162.   console.error('this is the second error logged');
    
  163.   return <div data-camelCasedAttribute="should-lower-case">{children}</div>;
    
  164. }
    
  165. 
    
  166. // $FlowFixMe[missing-local-annot]
    
  167. function ComponentWithMissingKey({children}) {
    
  168.   return [<div />];
    
  169. }
    
  170. 
    
  171. function ComponentWithSymbolWarning() {
    
  172.   console.warn('this is a symbol', Symbol('foo'));
    
  173.   console.error('this is a symbol', Symbol.for('bar'));
    
  174.   return null;
    
  175. }
    
  176. 
    
  177. export default function ErrorsAndWarnings(): React.Node {
    
  178.   const [count, setCount] = useState(0);
    
  179.   const handleClick = () => setCount(count + 1);
    
  180.   return (
    
  181.     <Fragment>
    
  182.       <h1>Inline warnings</h1>
    
  183.       <button onClick={handleClick}>Update {count > 0 ? count : ''}</button>
    
  184.       <ComponentWithMissingKey />
    
  185.       <WarnDuringRender />
    
  186.       <WarnOnMount />
    
  187.       <WarnOnUpdate />
    
  188.       {count === 0 ? <WarnOnUnmount /> : null}
    
  189.       {count === 0 ? <WarnOnMount /> : null}
    
  190.       <ErrorDuringRender />
    
  191.       <ErrorOnMount />
    
  192.       <ErrorOnUpdate />
    
  193.       {count === 0 ? <ErrorOnUnmount /> : null}
    
  194.       <ErrorAndWarningDuringRender />
    
  195.       <ErrorAndWarningOnMount />
    
  196.       <ErrorAndWarningOnUpdate />
    
  197.       {count === 0 ? <ErrorAndWarningOnUnmount /> : null}
    
  198.       <ErrorWithMultipleArgs />
    
  199.       <ErrorWithStringSubstitutions />
    
  200.       <ReactErrorOnHostComponent />
    
  201.       <ReallyLongErrorMessageThatWillCauseTextToBeTruncated />
    
  202.       <DuplicateWarningsAndErrors />
    
  203.       <MultipleWarningsAndErrors />
    
  204.       <ComponentWithSymbolWarning />
    
  205.     </Fragment>
    
  206.   );
    
  207. }