Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

Sync with reactjs.org @ 3ff6fe87 #118

Open
wants to merge 921 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
921 commits
Select commit Hold shift + click to select a range
176b93c
[Beta] Higher-level comments in useCallback
gaearon Sep 15, 2022
8e422e0
stricter wording
gaearon Sep 15, 2022
25ced88
emoji
gaearon Sep 15, 2022
a6322a4
fix mistake
gaearon Sep 15, 2022
e14de80
align wording
gaearon Sep 15, 2022
1517828
tweak wording
gaearon Sep 15, 2022
94e99f3
add a break
gaearon Sep 15, 2022
fd46d48
[beta] Add flushSync docs (#4930)
rickhanlonii Sep 15, 2022
651d31f
[Beta] Fragment edits (#5067)
gaearon Sep 15, 2022
348d140
Fix formatting
gaearon Sep 15, 2022
ec0292b
[Beta] forwardRef API (#5068)
gaearon Sep 15, 2022
5ceec20
[Beta] Initial API doc for Suspense (#4955)
acdlite Sep 15, 2022
954ef33
[Beta] lazy API (#5069)
gaearon Sep 15, 2022
0813c24
[Beta] Ensure forwardRef API docs use pattern that ensures a display …
eps1lon Sep 15, 2022
62d1ffe
tweak
gaearon Sep 15, 2022
da47b1a
Bump numbers
gaearon Sep 15, 2022
8d63e0d
[beta] Added memo API reference page (#5059)
davidmccabe Sep 15, 2022
76d14c8
oops
gaearon Sep 15, 2022
75563fe
Fix signature
gaearon Sep 15, 2022
5bcae4f
Fixed the challenge 4 expected output when initial state of "showForm…
kaushalyap Sep 16, 2022
d83e0aa
Small typo fix with forwardRef (#5075)
srt32 Sep 17, 2022
a6c164d
Fix a mistake
gaearon Sep 17, 2022
841d3d1
[Beta]: fix typo on you-might-not-need-an-effect (#5077)
ElForastero Sep 17, 2022
a050621
reactjsday-verona-italy-2022 (#5080)
lxmarinkovic Sep 19, 2022
675e0cf
updating upcoming React conferences (#4988)
robhrt7 Sep 20, 2022
d1fee87
[Beta] fix typo (#5082)
zqran Sep 20, 2022
8f6a4bf
[Beta] Fix some dead links
gaearon Sep 21, 2022
f9d4dda
[Beta] useMemo & useCallback edits (#5087)
gaearon Sep 22, 2022
5812e54
Removed extra closing curly braces from challenge 5 (#5088)
kaushalyap Sep 22, 2022
8a9efff
[Beta] Tweak loop guidance
gaearon Sep 22, 2022
97cfcc0
[Beta] Unified api format (#5090)
zqran Sep 22, 2022
a0bc4d2
[Beta] fix(SandpackConsole): avoid unsubscribing the logs listeners (…
danilowoz Sep 22, 2022
7030761
react-global-22.v2 (#5092)
lxmarinkovic Sep 22, 2022
c5d300e
Remove unnecessary fromatting
gaearon Sep 22, 2022
17dca33
Add semi
gaearon Sep 22, 2022
23218f6
removed unused useState (#5095)
kaushalyap Sep 23, 2022
caab52a
[Beta] Fix/extracting state logic into a reducer typo (#5096)
gsong Sep 23, 2022
6329438
[Beta] build: ignore markdown files in content (#5098)
gsong Sep 23, 2022
e0720af
[beta] Update CodeStep colors (#5089)
rickhanlonii Sep 23, 2022
59f0f98
[Beta] Tweak colors
gaearon Sep 23, 2022
4ff4d8f
Tweak the experimental notice
gaearon Sep 23, 2022
0826c79
Hide package.json where it is not relevant
gaearon Sep 23, 2022
bd0f7c0
[Beta] Use React versions from package.json (#5100)
gaearon Sep 23, 2022
d56aec2
[Beta] Remove inline useEvent impl (#5101)
gaearon Sep 23, 2022
26fc12c
[Beta] Remove linter TODOs (#5102)
gaearon Sep 24, 2022
4c37115
[Beta] Code style tweaks (#5104)
gaearon Sep 24, 2022
402581e
[Beta] Bump React/Next (#5105)
gaearon Sep 24, 2022
fcd0ca3
Revert "ts"
gaearon Sep 24, 2022
477bafa
Revert "useEvent"
gaearon Sep 24, 2022
372f852
[Beta] Next patch to fail on errors (#5106)
gaearon Sep 24, 2022
b59b64f
[Beta] Upgrade to MDX 2 (#5107)
gaearon Sep 24, 2022
e166848
Added RenderATL 2023 (#5108)
ThugDebugger Sep 24, 2022
2ad2bb3
Fix typo (#5111)
thomcleary Sep 25, 2022
6b4fe35
[Beta] Fully SSR CodeBlock (#5110)
gaearon Sep 25, 2022
c8bf6f8
[Beta] Fix CSS for long highlight lines
gaearon Sep 25, 2022
4f04184
[Beta] Optimize editor re-renders (#5113)
gaearon Sep 25, 2022
e3073b0
[Beta] Fix some CSS (#5114)
gaearon Sep 25, 2022
2a083f9
[Beta] Remove unused prop from context examples (#5117)
thomcleary Sep 26, 2022
1a69206
fix typo in useMemo() documentation [BETA] (#5119)
skromez Sep 26, 2022
ab8c1a4
Fix HTML and CSS highlighting
gaearon Sep 26, 2022
ed37a7d
[Beta] Disable runtime CSS-in-JS (#5122)
gaearon Sep 27, 2022
931fd96
[Beta] Exclude Markdown parser (#5123)
gaearon Sep 27, 2022
2805880
Remove bold from codestep
gaearon Sep 27, 2022
ea5810b
tweak landing copy
gaearon Sep 27, 2022
54e6276
[Beta] Fix header IDs (#5128)
gaearon Sep 28, 2022
8ae813f
[Beta] useEffect API (#5103)
gaearon Sep 29, 2022
edd2f4e
typo
gaearon Sep 29, 2022
f75d0e2
[Beta] Don't nest components (#5132)
gaearon Sep 29, 2022
004287e
grammar
gaearon Sep 29, 2022
9d7feb9
Tweak
gaearon Sep 29, 2022
d7761ed
Bump API to 70%
gaearon Sep 29, 2022
b6983c3
Fix lint
gaearon Sep 29, 2022
e30bfe8
[Beta] Add a survey (#5133)
gaearon Sep 29, 2022
fd81031
Point old site banner at Beta docs (#5134)
gaearon Sep 29, 2022
2e57382
Bolder CTA
gaearon Sep 29, 2022
3031668
Fix link
gaearon Sep 29, 2022
fbd8c82
Fix React Router 6.4+ link (#5135)
esvyridov Sep 29, 2022
35627be
Update my twitter name (#5141)
poteto Oct 1, 2022
664dd57
[Beta] Fix typos in 'Lifecycle of Reactive Effects' challenge descrip…
thomcleary Oct 2, 2022
45e3c1b
[Beta] Fixes for install instructions
gaearon Oct 3, 2022
3a9b0c8
[beta] fix: cleanup resize listener (#4847)
shanpriyan Oct 4, 2022
7de3a0b
[Beta] Added documentation for React.createFactory (#5120)
arati-1 Oct 4, 2022
1205097
[Beta] Add Alternatives to createFactory API (#5149)
gaearon Oct 4, 2022
88a2e53
fix typo
gaearon Oct 4, 2022
d9915ca
fix
gaearon Oct 4, 2022
8379534
[Beta] useId API (#5150)
gaearon Oct 4, 2022
b99298a
oops
gaearon Oct 4, 2022
7b0e3bd
[beta] Sandpack: fix package.json dependencies & remove cm-markdown d…
danilowoz Oct 4, 2022
440741d
[Beta] isValidElement API (#5152)
gaearon Oct 4, 2022
a224f9d
[Beta] Accurate MDX line numbers (#5153)
gaearon Oct 4, 2022
c741dd4
Fix
gaearon Oct 4, 2022
f24bc19
[Beta] createElement API (#5154)
gaearon Oct 5, 2022
6dcdaac
tweaks
gaearon Oct 5, 2022
fa30ccd
fix
gaearon Oct 5, 2022
9af5d8d
[Beta] useImperativeHandle API (#5157)
gaearon Oct 5, 2022
e6bc8db
[Beta] Remove some polyfills (#5158)
gaearon Oct 6, 2022
f3420fd
[beta] Sandpack: provide bare components and move styles (#5124)
danilowoz Oct 6, 2022
25d4589
[Beta] Prefetch CodeBlock (#5159)
gaearon Oct 6, 2022
3ac36ff
[Beta] Fix code styles (#5162)
gaearon Oct 7, 2022
06ab241
[Beta] Children API (#5163)
gaearon Oct 7, 2022
fba9eab
remove unused imports
gaearon Oct 7, 2022
9ccea25
[Beta] fix typo in 'Removing Effect Dependencies' (#5167)
thomcleary Oct 8, 2022
d07016a
[Beta] Rename Gotcha component to Pitfall (#5172)
alvarlagerlof Oct 9, 2022
8fe817e
[Beta] fix: gutter overlap with sandpack code on mobile (#5170)
shanpriyan Oct 16, 2022
641f20a
Scroll behavior (#5182)
AdnanOlarmmi Oct 17, 2022
ec6c673
fix: broken link for render-and-commt (#5184)
jukrb0x Oct 18, 2022
c69ff23
Revert "Scroll behavior (#5182)" (#5186)
gaearon Oct 18, 2022
30cafef
Fix 'queueing a series of state changes->updates' typo in beta docs (…
melissapthai Oct 18, 2022
415751c
[Beta] Remove superfluous IllustrationBlock title prop
gaearon Oct 18, 2022
0867cc1
[Beta] Show illustration credit on hover/tap (#5188)
gaearon Oct 18, 2022
e698f2f
[beta] broken links in updating-objects-in-state (#5190)
jukrb0x Oct 19, 2022
7e98d1f
fix(beta): removes debug console.log (#5189)
danecando Oct 19, 2022
d0a809a
[Beta] Note on Children vs children
gaearon Oct 19, 2022
36656af
[beta] Fix typo on apis/react-dom/render (#5191)
eps1lon Oct 19, 2022
d483aeb
[Beta] cloneElement API (#5194)
gaearon Oct 19, 2022
8a22e6e
[Beta] Sandpack bundler improvements (#5164)
danilowoz Oct 25, 2022
5d1cac5
Update 2022-03-08-react-18-upgrade-guide.md (#5208)
claidler Oct 26, 2022
8ab1291
[Beta] Sandpack: fix accessibility issue on Codeeditor (#5216)
danilowoz Oct 28, 2022
f4d42d6
[Beta] fix typo in apis/react/cloneElement (#5201)
SukkaW Oct 29, 2022
e21b37c
[Beta] Add missing dependencies (#5220)
holazz Oct 29, 2022
4df7cce
Fix broken links (#5225)
EzraBerendsen Oct 31, 2022
751a13f
Add github repo link in the footer (#5204)
arafatiqbal Oct 31, 2022
dee6aed
[Beta] fix useMemo API doc error. (#5224)
webpig Nov 1, 2022
fc7bd4d
Fix typo (#5222)
npentrel Nov 1, 2022
822330c
fix #5212 (#5213)
xnivaxhzne Nov 3, 2022
ec368f4
Update SandpackRoot.tsx (#5247)
danilowoz Nov 7, 2022
3915ef3
Add App.js Conf 2023 to the conferences page (#5248)
tsapeta Nov 7, 2022
27152d3
chore: move conf (#5249)
harish-sethuraman Nov 7, 2022
dc20245
Fix createContext href in React APIs (#5245)
AlekseiPopovDev Nov 8, 2022
40251d2
fix #5210 (#5211)
xnivaxhzne Nov 9, 2022
06ae637
Change footer link to React repo
gaearon Nov 11, 2022
3bba430
[Beta] Add missing styles to search box in modal (#5234)
zqianem Nov 13, 2022
bc39165
docs: Fix a broken link, add a missing quote (#5260)
aleksandr-kiliushin Nov 14, 2022
29b163a
Add "Meta Front-End Developer Professional Certificate" to Paid Cours…
hstarikov-coursera Nov 14, 2022
dd52cdd
[Beta] Remove remaining use of embed: scheme (#5265)
gaearon Nov 14, 2022
9d5d1e2
Update with correct index (#5266)
arafatiqbal Nov 15, 2022
eceab8f
[Beta] Fix toc overflow (#5267)
gaearon Nov 15, 2022
c581381
[Beta] React.Component API (#5196)
gaearon Nov 15, 2022
15e5bac
[Beta] Update text with cloneElement (#5268)
dhavall08 Nov 15, 2022
d2bf257
Clarify example
gaearon Nov 16, 2022
b44e18e
Add note about getSnapshotBeforeUpdate
gaearon Nov 16, 2022
081b568
[Beta] createRef API (#5270)
gaearon Nov 16, 2022
501de4a
[Beta] PureComponent API (#5271)
gaearon Nov 16, 2022
5e5eb21
[Beta] useDebugValue API (#5272)
gaearon Nov 16, 2022
543db5b
Fix title
gaearon Nov 16, 2022
28f30b4
Fix typo
gaearon Nov 16, 2022
1503e6b
[Beta] Fix Defining frameId in useAnimationLoop (#5277)
madany01 Nov 18, 2022
e50e563
Added undefined to in the list of possible return types of render fun…
kunxl-gg Nov 18, 2022
2896038
[Beta] Remove nav fadein
gaearon Nov 21, 2022
c19a34b
Fix typo in bookmark (#5279)
uthbees Nov 22, 2022
2381149
chore: its -> it is, to 1 line (#5292)
marcelrsoub Nov 25, 2022
5beee0a
fix: Use relative LICENSE-DOCS path in README (#5294)
andrewbrennanfr Nov 25, 2022
1a641bb
[Beta] Revamp navigation (#5287)
gaearon Nov 25, 2022
b562a4f
Rename breadcrumb
gaearon Nov 28, 2022
eef0910
Rename
gaearon Nov 28, 2022
a05c1d9
Add ReactNext 2023 (#5300)
adamkleingit Nov 29, 2022
f35d831
Fix key error (#5302)
rickhanlonii Nov 29, 2022
ed20748
[Beta] Rewrite Suspense API, add useDeferredValue API (#5308)
gaearon Dec 1, 2022
2128e1e
Update the link to the Node.js stream module (#5298)
xfq Dec 2, 2022
b3b6edd
[Beta] Add deps to useEffect example
gaearon Dec 2, 2022
2e7b147
Update acdlite picture (#5313)
acdlite Dec 2, 2022
cb9854a
[Beta] Add link anchor for ExpandableExample (Deep Dive) (#5310)
ibarapascal Dec 2, 2022
5414129
[Beta] Update the bundler (#5319)
gaearon Dec 5, 2022
e162995
[Beta] useTransition API (#5311)
gaearon Dec 6, 2022
2246611
fix: correct order of future conference dates content (#5307)
techieeliot Dec 6, 2022
640f42e
[Beta] useSyncExternalStore API (#5325)
gaearon Dec 7, 2022
2e539fa
[Beta] Anchor for individual challenges & deepdive (#5318)
ibarapascal Dec 7, 2022
51f0d2d
[API] Legacy renderTo* SSR methods (#5326)
gaearon Dec 7, 2022
583f9a7
Add missing stub for Profiler
gaearon Dec 7, 2022
e342965
Consistency naming tweaks
gaearon Dec 8, 2022
47916ff
[Beta] Fix broken links
gaearon Dec 8, 2022
c086b13
[beta] Add unmountComponentAtNode (#5328)
rickhanlonii Dec 8, 2022
a08caba
[Beta] Docs Contributors page (#5330)
gaearon Dec 8, 2022
a234788
Update reusing-logic-with-custom-hooks.md (#5331)
zetaraku Dec 8, 2022
e544ae4
Update team pages (#5329)
josephsavona Dec 8, 2022
cc1687b
[Beta] Fix a word from useMemo to useCallback (#5334)
dhavall08 Dec 8, 2022
3bd9bed
[Beta] renderToPipeableStream API (#5339)
gaearon Dec 9, 2022
0e508cb
Typo
gaearon Dec 9, 2022
d1a3e17
Typo
gaearon Dec 9, 2022
e6587b3
edits
gaearon Dec 11, 2022
b2e8dbf
[Beta] renderToReadableStream API (#5346)
gaearon Dec 11, 2022
01ec244
fix typo (#5343)
shuding Dec 11, 2022
84efcd3
[Beta] Edits to hydrateRoot
gaearon Dec 11, 2022
c883f62
typo
gaearon Dec 11, 2022
8bf3b48
[Beta] startTransition API (#5354)
gaearon Dec 12, 2022
c68c36f
[Beta] Profiler API (#5355)
gaearon Dec 12, 2022
45b1068
[Beta] Fix some code blocks
gaearon Dec 12, 2022
6031b00
[beta] Fix Chai recipe in docs (#5342)
ashrene-roy Dec 12, 2022
cfa9498
Fix link to new URL (#5281)
castor4bit Dec 12, 2022
ca61341
[Beta] Fixed a dead link in useTransition.md (#5356)
mihail-8480 Dec 13, 2022
bad27d1
[beta] Add StrictMode docs (#5340)
rickhanlonii Dec 13, 2022
c2566a5
[beta] Add findDOMNode (#5357)
rickhanlonii Dec 14, 2022
9eca28f
Tweak header
gaearon Dec 14, 2022
5d65144
Tweaks
gaearon Dec 14, 2022
06d472d
[Beta] Fixed Semicolon missing in a code snippet. #5337 (#5360)
abhinandanwadwa Dec 14, 2022
3bb6d8c
[Beta] createPortal API (#5362)
gaearon Dec 14, 2022
596b50c
[Beta] Split "Components" and "APIs" (#5363)
gaearon Dec 14, 2022
7a9fe8d
Wording tweak
gaearon Dec 14, 2022
3d87a27
[Beta] useInsertionEffect API (#5364)
gaearon Dec 14, 2022
98bb99e
Fix typo
gaearon Dec 15, 2022
24a3e04
Fix typo
gaearon Dec 15, 2022
add83fa
[Beta] Highlight <Foo> and <foo> differently (#5368)
gaearon Dec 16, 2022
a7f4260
Fix typo (#5371)
mathmarqq Dec 16, 2022
a8db9c0
[Beta] useLayoutEffect API (#5372)
gaearon Dec 16, 2022
1aadd78
Fix copypasta
gaearon Dec 16, 2022
84a1085
More credits
gaearon Dec 16, 2022
119177b
[Beta] useEvent -> useEffectEvent (#5373)
gaearon Dec 16, 2022
d542994
Typo
gaearon Dec 16, 2022
c4d2a6d
[Beta] Reorder example
gaearon Dec 17, 2022
5385031
[Beta] Fix scroll jumps on navigating to fragments (#5375)
gaearon Dec 17, 2022
6faa4f5
Add missing patch for #5368
gaearon Dec 17, 2022
868d525
Update index.md
gaearon Dec 17, 2022
966b7b8
[Beta] Move search outside tabs (#5389)
gaearon Dec 20, 2022
ff22655
Adding a minor grammatical correction. (#5388)
rahulrao0209 Dec 23, 2022
39b9599
Remove stale RFC link
gaearon Dec 23, 2022
dc4d82b
Change 'options object' to 'createOptions function' (#5394)
rahulrao0209 Dec 24, 2022
89ad619
useTransition add semicolon (#5384)
2239559319 Dec 24, 2022
167603a
Making serverUrl a reactive dependency for the provided example. (#5392)
rahulrao0209 Dec 24, 2022
d981e00
[Beta] react-dom: Components (#5383)
gaearon Dec 24, 2022
e2a0f2e
[Beta] Remove TOC from short pages
gaearon Dec 24, 2022
81b5f81
[beta] Tic-tac-toe tutorial rewrite (#5352)
mattcarrollcode Dec 24, 2022
302fb7a
Bump the numbers
gaearon Dec 24, 2022
bd9f3ea
Typo
gaearon Dec 24, 2022
147bab9
[Beta] Move Reference before Usage (#5399)
gaearon Dec 25, 2022
c793076
[Beta] APIs -> Reference (#5400)
gaearon Dec 25, 2022
88e689e
Always link to Usage for consistency
gaearon Dec 25, 2022
3473846
Fix above/below
gaearon Dec 25, 2022
8d51b16
[Beta] Remove some duplicated banners
gaearon Dec 25, 2022
4b68508
[Beta] Misc edits
gaearon Dec 25, 2022
20252cb
fix(typos): some small typos (#5401)
pfongkye Dec 26, 2022
ddde7e8
[Beta] Sidebar groups (#5402)
gaearon Dec 26, 2022
45e4b52
Fixed property "value" typo'd as "values" (#5404)
Dec 27, 2022
2a3bcb6
Minor grammatical correction (#5406)
rahulrao0209 Dec 27, 2022
bcf7759
[Beta] Fixes typo in editor-setup page (#5413)
filipenevola Dec 28, 2022
afb7d7a
Fixes a typo (#5411)
acharyasaagar Dec 29, 2022
c7efb5c
Minor grammatical correction (#5407)
rahulrao0209 Dec 29, 2022
33c4d58
Fix 404 for json file (#5403)
domscript Dec 29, 2022
f741a42
Fix #5412
gaearon Dec 29, 2022
9cd0db0
fix(typo): add missing closing character (#5415)
pfongkye Dec 29, 2022
e77ba1e
[beta] Fix inconsistent anchor link on `flushSync` page (#5429)
eps1lon Jan 1, 2023
0eba7f6
Fix typo in tutorial-tic-tac-toe.md (#5436)
derrekcoleman Jan 5, 2023
46b5a69
Fix typo in tutorial-tic-tac-toe.md (#5438)
rijavecb Jan 5, 2023
e8a64f6
Fix link
gaearon Jan 5, 2023
eefa33a
Fix typo in tutorial
sophiebits Jan 5, 2023
44390cd
Fix for ReactDOM.createRoot() example (#5437)
chalder Jan 6, 2023
05bf01d
[Beta] Add missing imports to ref pages (#5442)
gaearon Jan 6, 2023
b4ae933
Add missing X in starter Square component (#5445)
SecondThundeR Jan 7, 2023
52b2d7d
Bump json5 from 1.0.1 to 1.0.2 in /beta (#5446)
dependabot[bot] Jan 8, 2023
3ff6fe8
Fix typos in Suspense.md, useDeferredValue.md & useTransition.md (#5450)
tryonelove Jan 8, 2023
0d8788f
merging all conflicts
react-translations-bot Jan 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[Beta] useSyncExternalStore API (#5325)
gaearon authored Dec 7, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 640f42ef7192f86b8b4dc65a2c1050deff53e90c
25 changes: 25 additions & 0 deletions beta/src/content/apis/react/Suspense.md
Original file line number Diff line number Diff line change
@@ -2496,6 +2496,31 @@ However, now imagine you're navigating between two different user profiles. In t
---
### Providing a fallback for server errors and server-only content {/*providing-a-fallback-for-server-errors-and-server-only-content*/}
If you use one of the [streaming server rendering APIs](/apis/react-dom/server) (or a framework that relies on them), React will also use your `<Suspense>` boundaries to handle errors on the server. If a component throws an error on the server, React will not abort the server render. Instead, it will find the closest `<Suspense>` component above it and include its fallback (such as a spinner) into the generated server HTML. The user will see a spinner instead of an error.
On the client, React will attempt to render the same component again. If it errors on the client too, React will throw the error and display the closest [error boundary.](/apis/react/Component#static-getderivedstatefromerror) However, if it does not error on the client, React will not display the error to the user since the content was eventually displayed successfully.
You can use this to opt out some components from rendering on the server. To do this, throw an error from them in the server environment and then wrap them in a `<Suspense>` boundary to replace their HTML with fallbacks:
```js
<Suspense fallback={<Loading />}>
<Chat />
</Suspense>

function Chat() {
if (typeof window === 'undefined') {
throw Error('Chat should only render on the client.');
}
// ...
}
```
The server HTML will include the loading indicator. It will be replaced by the `Chat` component on the client.
---
## Reference {/*reference*/}
### `Suspense` {/*suspense*/}
420 changes: 412 additions & 8 deletions beta/src/content/apis/react/useSyncExternalStore.md
Original file line number Diff line number Diff line change
@@ -2,21 +2,425 @@
title: useSyncExternalStore
---

<Wip>
<Intro>

This section is incomplete, please see the old docs for [useSyncExternalStore.](https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore)
`useSyncExternalStore` is a React Hook that lets you subscribe to an external store.

</Wip>
```js
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)
```
</Intro>
<Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Subscribing to an external store {/*subscribing-to-an-external-store*/}
Most of your React components will only read data from their [props,](/learn/passing-props-to-a-component) [state,](/apis/react/useState) and [context.](/apis/react/useContext) However, sometimes a component needs to read some data from some store outside of React that changes over time. This includes:
* Third-party state management libraries that hold state outside of React.
* Browser APIs that expose a mutable value and events to subscribe to its changes.
Call `useSyncExternalStore` at the top level of your component to read a value from an external data store.
```js [[1, 5, "todosStore.subscribe"], [2, 5, "todosStore.getSnapshot"], [3, 5, "todos", 0]]
import { useSyncExternalStore } from 'react';
import { todosStore } from './todoStore.js';

function TodosApp() {
const todos = useSyncExternalStore(todosStore.subscribe, todosStore.getSnapshot);
// ...
}
```
It returns the <CodeStep step={3}>snapshot</CodeStep> of the data in the store. You need to pass two functions as arguments:
1. The <CodeStep step={1}>`subscribe` function</CodeStep> should subscribe to the store and return a function that unsubscribes.
2. The <CodeStep step={2}>`getSnapshot` function</CodeStep> should read a snapshot of the data from the store.
React will use these functions to keep your component subscribed to the store and re-render it on changes.
`useSyncExternalStore` is a hook recommended for reading and subscribing from external data sources in a way that’s compatible with concurrent rendering features like selective hydration and time slicing.
For example, in the sandbox below, `todosStore` is implemented as an external store that stores data outside of React. The `TodosApp` component connects to that external store with the `useSyncExternalStore` Hook.
<Sandpack>
```js
const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?);
import { useSyncExternalStore } from 'react';
import { todosStore } from './todoStore.js';

export default function TodosApp() {
const todos = useSyncExternalStore(todosStore.subscribe, todosStore.getSnapshot);
return (
<>
<button onClick={() => todosStore.addTodo()}>Add todo</button>
<hr />
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</>
);
}
```
</Intro>
```js todoStore.js
// This is an example of a third-party store
// that you might need to integrate with React.

<InlineToc />
// If your app is fully built with React,
// we recommend using React state instead.

let nextId = 0;
let todos = [{ id: nextId++, text: 'Todo #1' }];
let listeners = [];

export const todosStore = {
addTodo() {
todos = [...todos, { id: nextId++, text: 'Todo #' + nextId }]
emitChange();
},
subscribe(listener) {
listeners = [...listeners, listener];
return () => {
listeners = listeners.filter(l => l !== listener);
};
},
getSnapshot() {
return todos;
}
};

function emitChange() {
for (let listener of listeners) {
listener();
}
}
```
</Sandpack>
<Note>
When possible, we recommend to use the built-in React state with [`useState`](/apis/react/useState) and [`useReducer`](/apis/react/useReducer) instead. The `useExternalSyncStore` API is mostly useful if you need to integrate with existing non-React code.
</Note>
---
### Subscribing to a browser API {/*subscribing-to-a-browser-api*/}
Another reason to add `useSyncExternalStore` is when you want to subscribe to some value exposed by the browser that changes over time. For example, suppose that you want your component to display whether the network connection is active. The browser exposes this information via a property called [`navigator.onLine`.](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) This value can change over time without React's knowledge, so you need to read it with `useSyncExternalStore`.
```js
import { useSyncExternalStore } from 'react';

function ChatIndicator() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
// ...
}
```
To implement the `getSnapshot` function, read the current value from the browser API:
```js
function getSnapshot() {
return navigator.onLine;
}
```
Next, you need to implement the `subscribe` function. For example, when `navigator.onLine` changes, the browser fires the [`online`](https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event) and [`offline`](https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event) events on the `window` object. You need to subscribe the `callback` argument to the corresponding events, and then return a function that cleans up the subscriptions:
```js
function subscribe(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
```
Now React knows how to read the value from the external `navigator.onLine` API and how to subscribe to its changes. Try to disconnect your device from the network and notice that the component re-renders in response:
<Sandpack>
```js
import { useSyncExternalStore } from 'react';

export default function ChatIndicator() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

function getSnapshot() {
return navigator.onLine;
}

function subscribe(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
```
</Sandpack>
---
### Extracting the logic to a custom Hook {/*extracting-the-logic-to-a-custom-hook*/}
Usually you won't write `useSyncExternalStore` directly in your components. Instead, you'll typically call it from your own custom Hook. This lets you use the same external store from different components.
For example, this custom `useOnlineStatus` Hook tracks whether the network is online:
```js {3,6}
import { useSyncExternalStore } from 'react';

export function useOnlineStatus() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
return isOnline;
}

function getSnapshot() {
// ...
}

function subscribe(callback) {
// ...
}
```
Now different components can call `useOnlineStatus` without repeating the underlying implementation:
<Sandpack>
```js
import { useOnlineStatus } from './useOnlineStatus.js';

function StatusBar() {
const isOnline = useOnlineStatus();
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

function SaveButton() {
const isOnline = useOnlineStatus();

function handleSaveClick() {
console.log('✅ Progress saved');
}

return (
<button disabled={!isOnline} onClick={handleSaveClick}>
{isOnline ? 'Save progress' : 'Reconnecting...'}
</button>
);
}

export default function App() {
return (
<>
<SaveButton />
<StatusBar />
</>
);
}
```
```js useOnlineStatus.js
import { useSyncExternalStore } from 'react';

export function useOnlineStatus() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
return isOnline;
}

function getSnapshot() {
return navigator.onLine;
}

function subscribe(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
```
</Sandpack>
---
### Adding support for server rendering {/*adding-support-for-server-rendering*/}
If your React app uses [server rendering,](/apis/react-dom/server) your React components will also run outside the browser environment to generate the initial HTML. This creates a few challenges when connecting to an external store:
- If you're connecting to a browser-only API, it won't work because it does not exist on the server.
- If you're connecting to a third-party data store, you'll need its data to match between the server and client.
To solve these issues, pass a `getServerSnapshot` function as the third argument to `useSyncExternalStore`:
```js {4,12-14}
import { useSyncExternalStore } from 'react';

export function useOnlineStatus() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
return isOnline;
}

function getSnapshot() {
return navigator.onLine;
}

function getServerSnapshot() {
return true; // Always show "Online" for server-generated HTML
}

function subscribe(callback) {
// ...
}
```
The `getServerSnapshot` function is similar to `getSnapshot`, but it runs only in two situations:
- It runs on the server when generating the HTML.
- It runs on the client during [hydration](/apis/react-dom/client/hydrateRoot), i.e. when React takes the server HTML and makes it interactive.
This lets you provide the initial snapshot value which will be used before the app becomes interactive. If there is no meaningful initial value for the server rendering, you can [force the component to render only on the client.](/apis/react/Suspense#providing-a-fallback-for-server-errors-and-server-only-content)
<Note>
Make sure that `getServerSnapshot` returns the same exact data on the initial client render as it returned on the server. For example, if `getServerSnapshot` returned some prepopulated store content on the server, you need to transfer this content to the client. One common way to do this is to emit a `<script>` tag that sets a global like `window.MY_STORE_DATA` during server rendering, and then read from that global on the client in `getServerSnapshot`. Your external store should provide instructions on how to do that.
</Note>
---
## Reference {/*reference*/}
### `useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)` {/*usesyncexternalstore*/}
Call `useSyncExternalStore` at the top level of your component to read a value from an external data store.
```js
import { useSyncExternalStore } from 'react';
import { todosStore } from './todoStore.js';

function TodosApp() {
const todos = useSyncExternalStore(todosStore.subscribe, todosStore.getSnapshot);
// ...
}
```
It returns the snapshot of the data in the store. You need to pass two functions as arguments:
1. The `subscribe` function should subscribe to the store and return a function that unsubscribes.
2. The `getSnapshot` function should read a snapshot of the data from the store.
[See more examples above.](#usage)
#### Parameters {/*parameters*/}
* `subscribe`: A function that takes a single `callback` argument and subscribes it to the store. When the store changes, it should invoke the provided `callback`. This will cause the component to re-render. The `subscribe` function should return a function that cleans up the subscription.
* `getSnapshot`: A function that returns a snapshot of the data in the store that's needed by the component. While the store has not changed, repeated calls to `getSnapshot` must return the same value. If the store changes and the returned value is different (as compared by [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), React will re-render the component.
* **optional** `getServerSnapshot`: A function that returns the initial snapshot of the data in the store. It will be used only during server rendering and during hydration of server-rendered content on the client. The server snapshot must be the same between the client and the server, and is usually serialized and passed from the server to the client. If this function is not provided, rendering the component on the server will throw an error.
#### Returns {/*returns*/}
The current snapshot of the store which you can use in your rendering logic.
#### Caveats {/*caveats*/}
* The store snapshot returned by `getSnapshot` must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.
* 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.
---
## Troubleshooting {/*troubleshooting*/}
### I'm getting an error: "The result of `getSnapshot` should be cached" {/*im-getting-an-error-the-result-of-getsnapshot-should-be-cached*/}
If you get this error, it means your `getSnapshot` function returns a new object every time it's called, for example:
```js {2-5}
function getSnapshot() {
// 🔴 Do not return always different objects from getSnapshot
return {
todos: myStore.todos
};
}
```
React will re-render the component if `getSnapshot` return value is different from the last time. This is why, if you always return a different value, you will enter an infinite loop and get this error.
Your `getSnapshot` object should only return a different object if something has actually changed. If your store contains immutable data, you can return that data directly:
```js {2-3}
function getSnapshot() {
// ✅ You can return immutable data
return myStore.todos;
}
```
If your store data is mutable, your `getSnapshot` function should return an immutable snapshot of it. This means it *does* need to create new objects, but it shouldn't do this for every single call. Instead, it should store the last calculated snapshot, and return the same snapshot as the last time if the data in the store has not changed. How you determine whether mutable data has changed depends on how your mutable store is implemented.
---
### My `subscribe` function gets called after every re-render {/*my-subscribe-function-gets-called-after-every-re-render*/}
This `subscribe` function is defined *inside* a component so it is different on every re-render:
```js {4-7}
function ChatIndicator() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);

// 🚩 Always a different function, so React will resubscribe on every re-render
function subscribe() {
// ...
}

// ...
}
```
React will resubscribe to your store if you pass a different `subscribe` function between re-renders. If this causes performance issues and you'd like to avoid resubscribing to the store, move the `subscribe` function outside:
```js {6-9}
function ChatIndicator() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
// ...
}

// ✅ Always the same function, so React won't need to resubscribe
function subscribe() {
// ...
}
```
Alternatively, wrap `subscribe` into [`useCallback`](/apis/react/useCallback) to only resubscribe when some argument changes:
```js {4-8}
function ChatIndicator({ userId }) {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);

// ✅ Same function as long as userId doesn't change
const subscribe = useCallback(() => {
// ...
}, [userId]);

// ...
}
```
3 changes: 1 addition & 2 deletions beta/src/sidebarAPIs.json
Original file line number Diff line number Diff line change
@@ -67,8 +67,7 @@
},
{
"title": "useSyncExternalStore",
"path": "/apis/react/useSyncExternalStore",
"wip": true
"path": "/apis/react/useSyncExternalStore"
},
{
"title": "useTransition",