Skip to content

Commit 2bccc68

Browse files
Normalize file paths in deadLinkChecker and update documentation links for clarity
1 parent 3104359 commit 2bccc68

File tree

4 files changed

+259
-4
lines changed

4 files changed

+259
-4
lines changed

scripts/deadLinkChecker.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ async function buildAnchorMap(files) {
8080
const content = await readFileWithCache(filePath);
8181
const anchors = extractAnchorsFromContent(content);
8282
if (anchors.size > 0) {
83-
anchorMap.set(filePath, anchors);
83+
// Normalize path to use consistent separators
84+
const normalizedPath = path.normalize(filePath);
85+
anchorMap.set(normalizedPath, anchors);
8486
}
8587
}
8688
}
@@ -244,7 +246,9 @@ async function validateLink(link) {
244246
}
245247
}
246248

247-
const fileAnchors = anchorMap.get(targetFile);
249+
// Normalize target file path for comparison with anchorMap keys
250+
const normalizedTargetFile = path.normalize(targetFile);
251+
const fileAnchors = anchorMap.get(normalizedTargetFile);
248252

249253
if (!fileAnchors || !fileAnchors.has(anchorId)) {
250254
return {

src/content/blog/2024/10/21/react-compiler-beta-release.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ React Compiler can also be used to compile libraries. Because React Compiler nee
7878

7979
Because your code is pre-compiled, users of your library will not need to have the compiler enabled in order to benefit from the automatic memoization applied to your library. If your library targets apps not yet on React 19, specify a minimum `target` and add `react-compiler-runtime` as a direct dependency. The runtime package will use the correct implementation of APIs depending on the application's version, and polyfill the missing APIs if necessary.
8080

81-
[You can find more docs on this here.](/reference/react-compiler/target#using-the-compiler-on-libraries)
81+
[You can find more docs on this here.](/reference/react-compiler/target#targeting-react-17-or-18)
8282

8383
## Opening up React Compiler Working Group to everyone {/*opening-up-react-compiler-working-group-to-everyone*/}
8484

src/content/reference/react-dom/client/hydrateRoot.md

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,257 @@ export default function App({counter}) {
374374
375375
It is uncommon to call [`root.render`](#root-render) on a hydrated root. Usually, you'll [update state](/reference/react/useState) inside one of the components instead.
376376
377+
### Error logging in production {/*error-logging-in-production*/}
378+
379+
By default, React will log all errors to the console. To implement your own error reporting, you can provide the optional error handler root options `onUncaughtError`, `onCaughtError` and `onRecoverableError`:
380+
381+
```js
382+
import { hydrateRoot } from "react-dom/client";
383+
import App from "./App.js";
384+
import { reportCaughtError } from "./reportError";
385+
386+
const container = document.getElementById("root");
387+
const root = hydrateRoot(container, <App />, {
388+
onCaughtError: (error, errorInfo) => {
389+
if (error.message !== "Known error") {
390+
reportCaughtError({
391+
error,
392+
componentStack: errorInfo.componentStack,
393+
});
394+
}
395+
},
396+
});
397+
```
398+
399+
The `onCaughtError` option is a function called with two arguments:
400+
401+
1. The `error` that was thrown.
402+
2. An `errorInfo` object that contains the `componentStack` of the error.
403+
404+
Together with `onUncaughtError` and `onRecoverableError`, you can implement your own error reporting system:
405+
406+
<Sandpack>
407+
408+
```html index.html hidden
409+
<!DOCTYPE html>
410+
<html>
411+
<head>
412+
<title>My app</title>
413+
</head>
414+
<body>
415+
<!--
416+
Error dialog HTML container is at the top of the document, but React will populate it via a portal.
417+
-->
418+
<div id="error-dialog"></div>
419+
<div id="root"></div>
420+
</body>
421+
</html>
422+
```
423+
424+
```js
425+
import { hydrateRoot } from "react-dom/client";
426+
import App from "./App.js";
427+
import {
428+
onCaughtErrorProd,
429+
onRecoverableErrorProd,
430+
onUncaughtErrorProd,
431+
} from "./reportError";
432+
433+
const container = document.getElementById("root");
434+
hydrateRoot(container, <App />, {
435+
// Keep in mind to remove these options in development to leverage
436+
// React's default handlers or implement your own overlay for development.
437+
// The handlers are only specfied unconditionally here for demonstration purposes.
438+
onCaughtError: onCaughtErrorProd,
439+
onRecoverableError: onRecoverableErrorProd,
440+
onUncaughtError: onUncaughtErrorProd,
441+
});
442+
```
443+
444+
```js src/reportError.js hidden
445+
// These are example error reporting functions.
446+
// You would integrate your own error reporting service here.
447+
export function onRecoverableErrorProd(error, errorInfo) {
448+
console.error(
449+
'Caught recoverable error',
450+
error,
451+
error.cause,
452+
errorInfo.componentStack,
453+
);
454+
}
455+
456+
export function onCaughtErrorProd(error, errorInfo) {
457+
console.error(
458+
'Caught error in a boundary',
459+
error,
460+
errorInfo.componentStack,
461+
);
462+
}
463+
464+
export function onUncaughtErrorProd(error, errorInfo) {
465+
console.error(
466+
'Uncaught error',
467+
error,
468+
errorInfo.componentStack,
469+
);
470+
}
471+
```
472+
473+
```js src/App.js
474+
import { useState } from 'react';
475+
import { ErrorBoundary } from "react-error-boundary";
476+
477+
export default function App() {
478+
const [error, setError] = useState(null);
479+
480+
function handleUnknownError() {
481+
setError("unknown");
482+
}
483+
484+
function handleKnownError() {
485+
setError("known");
486+
}
487+
488+
return (
489+
<>
490+
<ErrorBoundary
491+
fallbackRender={fallbackRender}
492+
>
493+
<h1>Error Logging in Production Example</h1>
494+
<p>
495+
In this example, error boundaries are used along with `onCaughtError`, `onUncaughtError` and `onRecoverableError` to log errors.
496+
</p>
497+
<p>
498+
Check the console to see the logged errors.
499+
</p>
500+
<p>
501+
`onCaughtError` will only log errors that are caught by an error boundary. `onUncaughtError` will log errors that are not caught. `onRecoverableError` will log errors that React can recover from.
502+
</p>
503+
<p>
504+
Try clicking the buttons below to trigger each type of error.
505+
</p>
506+
<Button
507+
onClick={handleKnownError}
508+
>
509+
Throw known error
510+
</Button>
511+
{' '}
512+
<Button
513+
onClick={handleUnknownError}
514+
>
515+
Throw unknown error
516+
</Button>
517+
{error != null && <Thrower error={error} />}
518+
</ErrorBoundary>
519+
</>
520+
);
521+
}
522+
523+
function fallbackRender({ resetErrorBoundary }) {
524+
return (
525+
<div role="alert">
526+
<h2>Something went wrong</h2>
527+
<button onClick={resetErrorBoundary}>
528+
Reset
529+
</button>
530+
</div>
531+
);
532+
}
533+
534+
function Thrower({error}) {
535+
if (error === "known") {
536+
throw new Error('Known error');
537+
} else {
538+
foo.bar = 'baz';
539+
}
540+
}
541+
542+
function Button({ children, onClick }) {
543+
const [active, setActive] = useState(false);
544+
let background = active ? 'pink' : 'white';
545+
return (
546+
<button
547+
style={{background}}
548+
onPointerDown={() => setActive(true)}
549+
onPointerUp={() => setActive(false)}
550+
onClick={onClick}
551+
>
552+
{children}
553+
</button>
554+
);
555+
}
556+
```
557+
558+
```json package.json hidden
559+
{
560+
"dependencies": {
561+
"react": "19.0.0",
562+
"react-dom": "19.0.0",
563+
"react-scripts": "^5.0.0",
564+
"react-error-boundary": "4.0.3"
565+
},
566+
"main": "/index.js"
567+
}
568+
```
569+
570+
```css styles.css hidden
571+
* {
572+
box-sizing: border-box;
573+
}
574+
575+
body {
576+
font-family: sans-serif;
577+
margin: 20px;
578+
padding: 0;
579+
}
580+
581+
h1 {
582+
margin-top: 0;
583+
font-size: 22px;
584+
}
585+
586+
h2 {
587+
margin-top: 0;
588+
font-size: 20px;
589+
}
590+
591+
h3 {
592+
margin-top: 0;
593+
font-size: 18px;
594+
}
595+
596+
h4 {
597+
margin-top: 0;
598+
font-size: 16px;
599+
}
600+
601+
h5 {
602+
margin-top: 0;
603+
font-size: 14px;
604+
}
605+
606+
h6 {
607+
margin-top: 0;
608+
font-size: 12px;
609+
}
610+
611+
code {
612+
font-size: 1.2em;
613+
}
614+
615+
ul {
616+
padding-inline-start: 20px;
617+
}
618+
619+
button {
620+
margin: 5px;
621+
}
622+
```
623+
624+
</Sandpack>
625+
626+
---
627+
377628
### Show a dialog for uncaught errors {/*show-a-dialog-for-uncaught-errors*/}
378629
379630
<Canary>

src/content/reference/react/use.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ export default async function App() {
343343
}
344344
```
345345
346-
But using `await` in a [Server Component](/reference/react/components#server-components) will block its rendering until the `await` statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
346+
But using `await` in a [Server Component](/reference/rsc/server-components) will block its rendering until the `await` statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
347347
348348
</DeepDive>
349349

0 commit comments

Comments
 (0)