diff --git a/package.json b/package.json
index 5ff6adbab..472ef79c9 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"next-remote-watch": "^1.0.0",
"parse-numeric-range": "^1.2.0",
"react": "^0.0.0-experimental-16d053d59-20230506",
- "react-collapsed": "npm:@gaearon/react-collapsed@3.1.0-forked.1",
+ "react-collapsed": "4.0.4",
"react-dom": "^0.0.0-experimental-16d053d59-20230506",
"remark-frontmatter": "^4.0.1",
"remark-gfm": "^3.0.1"
diff --git a/src/components/Layout/Sidebar/SidebarRouteTree.tsx b/src/components/Layout/Sidebar/SidebarRouteTree.tsx
index 9a0dd23f5..a9fa575b5 100644
--- a/src/components/Layout/Sidebar/SidebarRouteTree.tsx
+++ b/src/components/Layout/Sidebar/SidebarRouteTree.tsx
@@ -7,7 +7,7 @@ import {useRef, useLayoutEffect, Fragment} from 'react';
import cn from 'classnames';
import {useRouter} from 'next/router';
import {SidebarLink} from './SidebarLink';
-import useCollapse from 'react-collapsed';
+import {useCollapse} from 'react-collapsed';
import usePendingRoute from 'hooks/usePendingRoute';
import type {RouteItem} from 'components/Layout/getRouteMeta';
diff --git a/src/components/Seo.tsx b/src/components/Seo.tsx
index d0dcaab75..79f19f87c 100644
--- a/src/components/Seo.tsx
+++ b/src/components/Seo.tsx
@@ -22,6 +22,7 @@ const deployedTranslations = [
'zh-hans',
'es',
'fr',
+ 'ja',
// We'll add more languages when they have enough content.
// Please DO NOT edit this list without a discussion in the reactjs/react.dev repo.
// It must be the same between all translations.
diff --git a/src/content/learn/typescript.md b/src/content/learn/typescript.md
index 56fa5be5b..727974b1c 100644
--- a/src/content/learn/typescript.md
+++ b/src/content/learn/typescript.md
@@ -284,7 +284,7 @@ export default App = AppTSX;
-This technique works when you have an default value which makes sense - but there are occasionally cases when you do not, and in those cases `null` can feel reasonable as a default value. However, to allow the type-system to understand your code, you need to explicitly set `ContextShape | null` on the `createContext`.
+This technique works when you have a default value which makes sense - but there are occasionally cases when you do not, and in those cases `null` can feel reasonable as a default value. However, to allow the type-system to understand your code, you need to explicitly set `ContextShape | null` on the `createContext`.
This causes the issue that you need to eliminate the `| null` in the type for context consumers. Our recommendation is to have the hook do a runtime check for it's existence and throw an error when not present:
@@ -460,4 +460,4 @@ We recommend the following resources:
- [React TypeScript Cheatsheet](https://react-typescript-cheatsheet.netlify.app/) is a community-maintained cheatsheet for using TypeScript with React, covering a lot of useful edge cases and providing more breadth than this document.
- - [TypeScript Community Discord](https://discord.com/invite/typescript) is a great place to ask questions and get help with TypeScript and React issues.
\ No newline at end of file
+ - [TypeScript Community Discord](https://discord.com/invite/typescript) is a great place to ask questions and get help with TypeScript and React issues.
diff --git a/src/content/reference/react/experimental_taintObjectReference.md b/src/content/reference/react/experimental_taintObjectReference.md
index ce91c3d0c..e3fd35a48 100644
--- a/src/content/reference/react/experimental_taintObjectReference.md
+++ b/src/content/reference/react/experimental_taintObjectReference.md
@@ -68,7 +68,7 @@ experimental_taintObjectReference(
-**Do not rely on just tainting for security.** Tainting an object doesn't prevent leaking of every possible derived value. For example, the clone of a tainted object will create a new untained object. Using data from a tainted object (e.g. `{secret: taintedObj.secret}`) will create a new value or object that is not tainted. Tainting is a layer of protection, a secure app will have multiple layers of protection, well designed APIs, and isolation patterns.
+**Do not rely on just tainting for security.** Tainting an object doesn't prevent leaking of every possible derived value. For example, the clone of a tainted object will create a new untained object. Using data from a tainted object (e.g. `{secret: taintedObj.secret}`) will create a new value or object that is not tainted. Tainting is a layer of protection; a secure app will have multiple layers of protection, well designed APIs, and isolation patterns.
diff --git a/src/content/reference/react/experimental_taintUniqueValue.md b/src/content/reference/react/experimental_taintUniqueValue.md
index eab73df5b..a67eebf77 100644
--- a/src/content/reference/react/experimental_taintUniqueValue.md
+++ b/src/content/reference/react/experimental_taintUniqueValue.md
@@ -130,7 +130,7 @@ In this example, the constant `password` is tainted. Then `password` is used to
Other similar ways of deriving new values from tainted values like concatenating it into a larger string, converting it to base64, or returning a substring create untained values.
-Tainting only protects against simple mistakes like explictly passing secret values to the client. Mistakes in calling the `taintUniqueValue` like using a global store outside of React, without the corresponding lifetime object, can cause the tainted value to become untainted. Tainting is a layer of protection, a secure app will have multiple layers of protection, well designed APIs, and isolation patterns.
+Tainting only protects against simple mistakes like explictly passing secret values to the client. Mistakes in calling the `taintUniqueValue` like using a global store outside of React, without the corresponding lifetime object, can cause the tainted value to become untainted. Tainting is a layer of protection; a secure app will have multiple layers of protection, well designed APIs, and isolation patterns.
diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md
index 4169e231e..955b751f8 100644
--- a/src/content/reference/react/useSyncExternalStore.md
+++ b/src/content/reference/react/useSyncExternalStore.md
@@ -57,6 +57,26 @@ The current snapshot of the store which you can use in your rendering logic.
* If a different `subscribe` function is passed during a re-render, React will re-subscribe to the store using the newly passed `subscribe` function. You can prevent this by declaring `subscribe` outside the component.
+* If the store is mutated during a [non-blocking transition update](/reference/react/useTransition), React will fall back to performing that update as blocking. Specifically, React will call `getSnapshot` a second time just before applying changes to the DOM. If it returns a different value than when it was called originally, React will restart the transition update from scratch, this time applying it as a blocking update, to ensure that every component on screen is reflecting the same version of the store.
+
+* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. The reason is that mutations to the external store cannot be [marked as non-blocking transition updates](/reference/react/useTransition), so they will trigger the nearest [`Suspense` fallback](/reference/react/Suspense), replacing already-rendered content on screen with a loading spinner, which typically makes a poor UX.
+
+ For example, the following are discouraged:
+
+ ```js
+ const LazyProductDetailPage = lazy(() => import('./ProductDetailPage.js'));
+
+ function ShoppingApp() {
+ const selectedProductId = useSyncExternalStore(...);
+
+ // ❌ Calling `use` with a Promise dependent on `selectedProductId`
+ const data = use(fetchItem(selectedProductId))
+
+ // ❌ Conditionally rendering a lazy component based on `selectedProductId`
+ return selectedProductId != null ? : ;
+ }
+ ```
+
---
## Usage {/*usage*/}
@@ -425,4 +445,4 @@ function ChatIndicator({ userId }) {
// ...
}
-```
\ No newline at end of file
+```
diff --git a/src/sidebarReference.json b/src/sidebarReference.json
index d1de30620..f9049956f 100644
--- a/src/sidebarReference.json
+++ b/src/sidebarReference.json
@@ -130,11 +130,13 @@
},
{
"title": "experimental_taintObjectReference",
- "path": "/reference/react/experimental_taintObjectReference"
+ "path": "/reference/react/experimental_taintObjectReference",
+ "canary": true
},
{
"title": "experimental_taintUniqueValue",
- "path": "/reference/react/experimental_taintUniqueValue"
+ "path": "/reference/react/experimental_taintUniqueValue",
+ "canary": true
}
]
},
diff --git a/yarn.lock b/yarn.lock
index 5819fa4fa..8a3183cd5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4797,11 +4797,6 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
periscopic@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.0.4.tgz#b3fbed0d1bc844976b977173ca2cd4a0ef4fa8d1"
@@ -5284,13 +5279,6 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-raf@^3.4.1:
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
- integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
- dependencies:
- performance-now "^2.1.0"
-
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@@ -5306,12 +5294,11 @@ raw-body@2.5.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
-"react-collapsed@npm:@gaearon/react-collapsed@3.1.0-forked.1":
- version "3.1.0-forked.1"
- resolved "https://registry.yarnpkg.com/@gaearon/react-collapsed/-/react-collapsed-3.1.0-forked.1.tgz#b287b81fc2af2971d7d7b523dc40b6cf116822ac"
- integrity sha512-QkW55Upl4eeOtnDMOxasafDtDwaF+DpYKvHq8KZoNz9P477iUH8Ik1YFYuqtI7UA8mHm1/z66LD678dZCXwEEg==
+react-collapsed@4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/react-collapsed/-/react-collapsed-4.0.4.tgz#4c6bce3a15286d43e95b6730ad70ec387a54caa9"
+ integrity sha512-8avvmnQxDYTgGZYVP9+3Z7doomxVEBoCkukpTmUHEIrAYvELZ5jNNfYCt/hCpHB6GmQbzZoDmnDupjsnQVgcCQ==
dependencies:
- raf "^3.4.1"
tiny-warning "^1.0.3"
react-devtools-inline@4.4.0: