mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[DevTools] chore: add useSyncExternalStore examples to shell (#34932)
Few examples of using `useSyncExternalStore` that can be useful for debugging hook tree reconstruction logic and hook names parsing feature.
This commit is contained in:
parent
ea0c17b095
commit
613cf80f26
|
|
@ -20,6 +20,7 @@ import SimpleValues from './SimpleValues';
|
|||
import SymbolKeys from './SymbolKeys';
|
||||
import UseMemoCache from './UseMemoCache';
|
||||
import UseEffectEvent from './UseEffectEvent';
|
||||
import UseSyncExternalStore from './UseSyncExternalStore';
|
||||
|
||||
// TODO Add Immutable JS example
|
||||
|
||||
|
|
@ -38,6 +39,7 @@ export default function InspectableElements(): React.Node {
|
|||
<SymbolKeys />
|
||||
<UseMemoCache />
|
||||
<UseEffectEvent />
|
||||
<UseSyncExternalStore />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
133
packages/react-devtools-shell/src/app/InspectableElements/UseSyncExternalStore.js
vendored
Normal file
133
packages/react-devtools-shell/src/app/InspectableElements/UseSyncExternalStore.js
vendored
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const {useState, useEffect, useSyncExternalStore} = React;
|
||||
|
||||
// Create a simple external store for demonstratio
|
||||
function createStore<T>(initialValue: T): {
|
||||
subscribe: (cb: () => void) => () => any,
|
||||
getSnapshot: () => T,
|
||||
setValue: (newValue: T) => void,
|
||||
} {
|
||||
let value = initialValue;
|
||||
const subscribers = new Set<() => void>();
|
||||
|
||||
return {
|
||||
subscribe(callback) {
|
||||
subscribers.add(callback);
|
||||
return () => subscribers.delete(callback);
|
||||
},
|
||||
getSnapshot() {
|
||||
return value;
|
||||
},
|
||||
setValue(newValue) {
|
||||
value = newValue;
|
||||
subscribers.forEach(callback => callback());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const counterStore = createStore(0);
|
||||
const themeStore = createStore('light');
|
||||
|
||||
export default function UseSyncExternalStore(): React.Node {
|
||||
return (
|
||||
<>
|
||||
<h2>useSyncExternalStore()</h2>
|
||||
<SingleHookCase />
|
||||
<HookTreeCase />
|
||||
<MultipleStoresCase />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SingleHookCase(): React.Node {
|
||||
const count = useSyncExternalStore(
|
||||
counterStore.subscribe,
|
||||
counterStore.getSnapshot,
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Single hook case</h3>
|
||||
<p>Count: {count}</p>
|
||||
<button onClick={() => counterStore.setValue(count + 1)}>
|
||||
Increment
|
||||
</button>
|
||||
<button onClick={() => counterStore.setValue(count - 1)}>
|
||||
Decrement
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function useCounter() {
|
||||
const count = useSyncExternalStore(
|
||||
counterStore.subscribe,
|
||||
counterStore.getSnapshot,
|
||||
);
|
||||
const [localState, setLocalState] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// Some effect
|
||||
}, [count]);
|
||||
|
||||
return {count, localState, setLocalState};
|
||||
}
|
||||
|
||||
function HookTreeCase(): React.Node {
|
||||
const {count, localState, setLocalState} = useCounter();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Hook tree case</h3>
|
||||
<p>External count: {count}</p>
|
||||
<p>Local state: {localState}</p>
|
||||
<button onClick={() => counterStore.setValue(count + 1)}>
|
||||
Increment External
|
||||
</button>
|
||||
<button onClick={() => setLocalState(localState + 1)}>
|
||||
Increment Local
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function useTheme() {
|
||||
const theme = useSyncExternalStore(
|
||||
themeStore.subscribe,
|
||||
themeStore.getSnapshot,
|
||||
);
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
function MultipleStoresCase() {
|
||||
const count = useSyncExternalStore(
|
||||
counterStore.subscribe,
|
||||
counterStore.getSnapshot,
|
||||
);
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<div style={{background: theme === 'dark' ? '#333' : '#fff'}}>
|
||||
<h3>Multiple stores case</h3>
|
||||
<p>Count: {count}</p>
|
||||
<p>Theme: {theme}</p>
|
||||
<button
|
||||
onClick={() =>
|
||||
themeStore.setValue(theme === 'light' ? 'dark' : 'light')
|
||||
}>
|
||||
Toggle Theme
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user