diff --git a/.env.production b/.env.production
index d25eb7dd4b..e403f96b68 100644
--- a/.env.production
+++ b/.env.production
@@ -1 +1 @@
-NEXT_PUBLIC_GA_TRACKING_ID = 'UA-41298772-4'
\ No newline at end of file
+NEXT_PUBLIC_GA_TRACKING_ID = 'G-B1E83PJ3RT'
\ No newline at end of file
diff --git a/package.json b/package.json
index 472ef79c91..b5e07d70a8 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,6 @@
"classnames": "^2.2.6",
"date-fns": "^2.16.1",
"debounce": "^1.2.1",
- "ga-lite": "^2.1.4",
"github-slugger": "^1.3.0",
"next": "^13.4.1",
"next-remote-watch": "^1.0.0",
diff --git a/src/components/Layout/Feedback.tsx b/src/components/Layout/Feedback.tsx
index 94e3a81a70..66ab928963 100644
--- a/src/components/Layout/Feedback.tsx
+++ b/src/components/Layout/Feedback.tsx
@@ -4,7 +4,6 @@
import {useState} from 'react';
import {useRouter} from 'next/router';
-import {ga} from '../../utils/analytics';
export function Feedback({onSubmit = () => {}}: {onSubmit?: () => void}) {
const {asPath} = useRouter();
@@ -48,14 +47,12 @@ const thumbsDownIcon = (
function sendGAEvent(isPositive: boolean) {
// Fragile. Don't change unless you've tested the network payload
// and verified that the right events actually show up in GA.
- ga(
- 'send',
- 'event',
- 'button',
- 'feedback',
- window.location.pathname,
- isPositive ? '1' : '0'
- );
+ // @ts-ignore
+ gtag('event', 'feedback', {
+ event_category: 'button',
+ event_label: window.location.pathname,
+ value: isPositive ? 1 : 0,
+ });
}
function SendFeedback({onSubmit}: {onSubmit: () => void}) {
diff --git a/src/components/MDX/Sandpack/Preview.tsx b/src/components/MDX/Sandpack/Preview.tsx
index 8d83d98678..059645550c 100644
--- a/src/components/MDX/Sandpack/Preview.tsx
+++ b/src/components/MDX/Sandpack/Preview.tsx
@@ -52,6 +52,12 @@ export function Preview({
rawError = null;
}
+ // When throwing a new Error in Sandpack - we want to disable the dev error dialog
+ // to show the Error Boundary fallback
+ if (rawError && rawError.message.includes(`throw Error('Example error')`)) {
+ rawError = null;
+ }
+
// Memoized because it's fed to debouncing.
const firstLintError = useMemo(() => {
if (lintErrors.length === 0) {
diff --git a/src/content/learn/describing-the-ui.md b/src/content/learn/describing-the-ui.md
index 8ac9e66fdb..a0ee098f3c 100644
--- a/src/content/learn/describing-the-ui.md
+++ b/src/content/learn/describing-the-ui.md
@@ -533,13 +533,21 @@ React 使用树形关系建模以展示组件和模块之间的关系。
React 渲染树是组件之间父子关系的表示。
-示例的 React 渲染树
+
+
+示例的 React 渲染树
+
+
位于树顶部、靠近根组件的组件被视为顶层组件。没有子组件的组件被称为叶子组件。对组件的这种分类对于理解数据流和渲染性能非常有用。
对 JavaScript 模块之间的关系进行建模是了解应用程序的另一种有用方式。我们将其称为模块依赖树。
-示例的模块依赖树
+
+
+示例的模块依赖树
+
+
构建工具经常使用依赖树来捆绑客户端下载和渲染所需的所有 JavaScript 代码。对于 React 应用程序,打包大小会导致用户体验退化。了解模块依赖树有助于调试此类问题。
diff --git a/src/content/reference/react/experimental_taintUniqueValue.md b/src/content/reference/react/experimental_taintUniqueValue.md
index 9d2c30b424..9cf7db206a 100644
--- a/src/content/reference/react/experimental_taintUniqueValue.md
+++ b/src/content/reference/react/experimental_taintUniqueValue.md
@@ -67,7 +67,8 @@ experimental_taintUniqueValue(
#### 注意 {/*caveats*/}
-- 从受标记的值派生新值可能会破坏标记保护。通过将受标记的值大写、将受标记的字符串值连接成较大的字符串、将受标记的值转换为 base64、对受标记的值进行子字符串操作以及其他类似的转换来创建的新值,除非明确调用 `taintUniqueValue` 标记这些新创建的值,否则它们不会受到标记。
+* 从受标记的值派生新值可能会破坏标记保护。通过将受标记的值大写、将受标记的字符串值连接成较大的字符串、将受标记的值转换为 base64、对受标记的值进行子字符串操作以及其他类似的转换来创建的新值,除非明确调用 `taintUniqueValue` 标记这些新创建的值,否则它们不会受到标记。
+* Do not use `taintUniqueValue` to protect low-entropy values such as PIN codes or phone numbers. If any value in a request is controlled by an attacker, they could infer which value is tainted by enumerating all possible values of the secret.
---
diff --git a/src/content/reference/react/useTransition.md b/src/content/reference/react/useTransition.md
index abeecb333e..cdfa651dba 100644
--- a/src/content/reference/react/useTransition.md
+++ b/src/content/reference/react/useTransition.md
@@ -1,5 +1,6 @@
---
title: useTransition
+canary: true
---
@@ -151,7 +152,7 @@ export default function TabContainer() {
function selectTab(nextTab) {
startTransition(() => {
- setTab(nextTab);
+ setTab(nextTab);
});
}
@@ -823,7 +824,7 @@ function use(promise) {
reason => {
promise.status = 'rejected';
promise.reason = reason;
- },
+ },
);
throw promise;
}
@@ -1017,7 +1018,7 @@ function use(promise) {
reason => {
promise.status = 'rejected';
promise.reason = reason;
- },
+ },
);
throw promise;
}
@@ -1288,7 +1289,7 @@ function use(promise) {
reason => {
promise.status = 'rejected';
promise.reason = reason;
- },
+ },
);
throw promise;
}
@@ -1332,7 +1333,7 @@ function use(promise) {
reason => {
promise.status = 'rejected';
promise.reason = reason;
- },
+ },
);
throw promise;
}
@@ -1379,9 +1380,9 @@ async function getBio() {
setTimeout(resolve, 500);
});
- return `The Beatles were an English rock band,
- formed in Liverpool in 1960, that comprised
- John Lennon, Paul McCartney, George Harrison
+ return `The Beatles were an English rock band,
+ formed in Liverpool in 1960, that comprised
+ John Lennon, Paul McCartney, George Harrison
and Ringo Starr.`;
}
@@ -1501,7 +1502,101 @@ main {
---
-## 疑难解答 {/*troubleshooting*/}
+### Displaying an error to users with a error boundary {/*displaying-an-error-to-users-with-error-boundary*/}
+
+
+
+Error Boundary for useTransition is currently only available in React's canary and experimental channels. Learn more about [React's release channels here](/community/versioning-policy#all-release-channels).
+
+
+
+If a function passed to `startTransition` throws an error, you can display an error to your user with an [error boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary). To use an error boundary, wrap the component where you are calling the `useTransition` in an error boundary. Once the function passed to `startTransition` errors, the fallback for the error boundary will be displayed.
+
+
+
+```js AddCommentContainer.js active
+import { useTransition } from "react";
+import { ErrorBoundary } from "react-error-boundary";
+
+export function AddCommentContainer() {
+ return (
+ ⚠️Something went wrong