useSyncExternalStore ಎಂಬುದು ಕಾಂಪೊನೆಂಟ್ (component) ಹೊರಗಿರುವ ಡೇಟಾವನ್ನು ರೀಯಾಕ್ಟ್ (React) ಹೊರತರುವಂತೆ ಮಾಡುತ್ತದೆ, ಇದರಿಂದ ಕನ್ಕರೆಂಟ್ ರೆಂಡರಿಂಗ್ (concurrent rendering) ಉಂಟುಮಾಡಬಹುದಾದ ದೃಶ್ಯ ದೋಷಗಳನ್ನು (visual glitches) ತಪ್ಪಿಸಬಹುದು. ಇದು useEffect ಬಳಸಿ ಹೊರಗಿನ ಮೌಲ್ಯಗಳನ್ನು ಲೋಕಲ್ ಸ್ಟೇಟ್ಗೆ (local state) ತರುವ ಹಳೆಯ ಪದ್ಧತಿಯನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ. ಈ ಹಳೆಯ ಪದ್ಧತಿಯು "tearing" ಅನ್ನು ಉಂಟುಮಾಡಬಹುದು – ಅಂದರೆ ಒಂದೇ ರೆಂಡರಿಂಗ್ ಸಮಯದಲ್ಲಿ UI ನ ವಿವಿಧ ಭಾಗಗಳು ವಿಭಿನ್ನ ಮೌಲ್ಯಗಳನ್ನು ತೋರಿಸುವುದು.
ಕನ್ಕರನ್ಸಿ (concurrency) ಅಡಿಯಲ್ಲಿ ಹಳೆಯ ಪದ್ಧತಿ ಏಕೆ ವಿಫಲವಾಗುತ್ತದೆ
React 18 ಕ್ಕಿಂತ ಮೊದಲು, ಸಾಮಾನ್ಯ ವಿಧಾನ ಹೀಗಿತ್ತು:
const [value, setValue] = useState(initial);
useEffect(() => {
const unsubscribe = externalSource.subscribe(v => setValue(v));
return unsubscribe;
}, []);
ಎಫೆಕ್ಟ್ (effect) ಕಾಂಪೊನೆಂಟ್ ರೆಂಡರ್ ಆದ ನಂತರ ಚಲಿಸುತ್ತದೆ. React ನ ಕನ್ಕರೆಂಟ್ ರೆಂಡರರ್ ರೆಂಡರಿಂಗ್ ಅನ್ನು ನಿಲ್ಲಿಸಲು, ರದ್ದುಗೊಳಿಸಲು ಅಥವಾ ಮರುಪ್ರದರ್ಶಿಸಲು (replay) ನಿರ್ಧರಿಸಿದಾಗ, ಸ್ಟೇಟ್ ಅನ್ನು ಓದುವ UI ಗಿಂತ ಭಿನ್ನವಾದ ಸಮಯದಲ್ಲಿ ಎಫೆಕ್ಟ್ ಕಾರ್ಯಗತಗೊಳ್ಳಬಹುದು. ಇದರ ಪರಿಣಾಮವಾಗಿ ಅಸಮತೋಲನ ಉಂಟಾಗುತ್ತದೆ: ಒಂದು ಕಾಂಪೊನೆಂಟ್ ಹಳೆಯ ಮೌಲ್ಯವನ್ನು ಓದಿದರೆ, ಇನ್ನೊಂದು ಹೊಸ ಮೌಲ್ಯವನ್ನು ಓದಬಹುದು, ಮತ್ತು ಪರದೆಯು ಕ್ಷಣಿಕವಾಗಿ ಅಸಂಗತ ಡೇಟಾವನ್ನು ತೋರಿಸುತ್ತದೆ. ಈ "tearing" ಸಂಪೂರ್ಣ ಸಿಂಕ್ರೋನಸ್ (synchronous) ಜಗತ್ತಿನಲ್ಲಿ ಹಾನಿಕಾರಕವಲ್ಲದಿದ್ದರೂ, React ಏಕಕಾಲದಲ್ಲಿ UI ನ ಹಲವಾರು ಆವೃತ್ತಿಗಳನ್ನು ರೆಂಡರ್ ಮಾಡುವಾಗ ಇದು ದೃಶ್ಯ ದೋಷವಾಗಿ (visible bug) ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ.
useSyncExternalStore ಸಮಸ್ಯೆಯನ್ನು ಹೇಗೆ ಪರಿಹರಿಸುತ್ತದೆ
ಈ ಹೂಕ್ (hook) ಎರಡು ಕಾಲ್ಬ್ಯಾಕ್ಗಳನ್ನು (callbacks) ಬಯಸುತ್ತದೆ:
- subscribe – ಇದು ಲಿಸನರ್ ಅನ್ನು (listener) ನೋಂದಾಯಿಸುತ್ತದೆ ಮತ್ತು ಅದನ್ನು ತೆಗೆದುಹಾಕುವ ಫಂಕ್ಷನ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ.
- getSnapshot – ಇದು ಹೊರಗಿನ ಮೂಲದ (external source) ಪ್ರಸ್ತುತ ಮೌಲ್ಯವನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ.
ಕಾಂಪೊನೆಂಟ್ ಮೌಂಟ್ (mount) ಆದಾಗ React subscribe ಅನ್ನು ಕರೆಯುತ್ತದೆ ಮತ್ತು ಅನ್ಮೌಂಟ್ (unmount) ಆದಾಗ ಅದನ್ನು ವಿಲೇವಾರಿ ಮಾಡುತ್ತದೆ. ಪ್ರತಿ ರೆಂಡರಿಂಗ್ ಸಮಯದಲ್ಲಿ ಇದು getSnapshot ಅನ್ನು ಕರೆಯುತ್ತದೆ ಮತ್ತು ಒಂದೇ ಎಕ್ಸ್ಟರ್ನಲ್ ಸ್ಟೋರ್ ಅನ್ನು ಬಳಸುವ ಎಲ್ಲಾ ಕಾಂಪೊನೆಂಟ್ಗಳು ನಿಖರವಾದ ಒಂದೇ ಸ್ನ್ಯಾಪ್ಶಾಟ್ ಅನ್ನು ಓದುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ. ಓದುವ ಪ್ರಕ್ರಿಯೆಯು ರೆಂಡರ್ ಹಂತದ ಒಳಗೇ ನಡೆಯುವುದರಿಂದ, ರೆಂಡರರ್ ಇಡೀ ಟ್ರೀ (tree) ಉದ್ದಕ್ಕೂ ಅಪ್ಡೇಟ್ಗಳನ್ನು ಸಮನ್ವಯಗೊಳಿಸಬಹುದು, ಇದರಿಂದ "tearing" ತಪ್ಪುತ್ತದೆ.
Zustand ಮತ್ತು Redux ನಂತಹ ಲೈಬ್ರರಿಗಳು ಈಗಾಗಲೇ ತಮ್ಮ ಸ್ಟೋರ್ಗಳನ್ನು ಈ ಹೂಕ್ನೊಂದಿಗೆ ಬಳಸುತ್ತವೆ, ಆದ್ದರಿಂದ ಅವು React 18 ರ ಕನ್ಕರೆಂಟ್ ಫೀಚರ್ಗಳೊಂದಿಗೆ ಸುಲಭವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತವೆ.
ಹೂಕ್ ತಪ್ಪಾಗಿ ಕೆಲಸ ಮಾಡದಂತೆ ತಡೆಯುವ ನಿಯಮಗಳು
- ಕಾಂಪೊನೆಂಟ್ಗೆ ಅಗತ್ಯವಿರುವಿದ್ದನ್ನು ಮಾತ್ರ ಹಿಂತಿರುಗಿಸಿ – ದೊಡ್ಡ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುವುದರಿಂದ ಪ್ರತಿ ಅಪ್ಡೇಟ್ನಲ್ಲಿ React ಆಳವಾದ ರಚನೆಗಳನ್ನು (deep structures) ಹೋಲ被迫ಪಡುತ್ತದೆ. ಸಣ್ಣ ಸ್ನ್ಯಾಪ್ಶಾಟ್ ಬದಲಾವಣೆಯ ಪತ್ತೆಯನ್ನು ಸುಲಭಗೊಳಿಸುತ್ತದೆ.
- ರೆಫರೆನ್ಷಿಯಲ್ ಐಡೆಂಟಿಟಿಯನ್ನು (referential identity) ಕಾಪಾಡಿ – ಹೊರಗಿನ ಮೌಲ್ಯವು ಬದಲಾಗಿಲ್ಲದಿದ್ದರೆ, getSnapshot ಒಂದೇ ಆಬ್ಜೆಕ್ಟ್ ರೆಫರೆನ್ಸ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸಬೇಕು. ಪ್ರತಿ ಬಾರಿ ಹೊಸ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುವುದರಿಂದ ಅನಂತ ರೆಂಡರ್ ಲೂಪ್ (infinite render loop) ಉಂಟಾಗುತ್ತದೆ, ಏಕೆಂದರೆ ಪ್ರತಿ ರೆಂಡರ್ನಲ್ಲಿ React ಬದಲಾವಣೆಯನ್ನು ಕಾಣುತ್ತದೆ.
- ಬಳಕೆಯನ್ನು ಎಕ್ಸ್ಟರ್ನಲ್ ಮೂಲಗಳಿಗೆ ಸೀಮಿತಗೊಳಿಸಿ – ಲೋಕಲ್ ಕಾಂಪೊನೆಂಟ್ ಸ್ಟೇಟ್ ಅನ್ನು
useStateಅಥವಾuseReducerನಲ್ಲಿ ಇಡಬೇಕು. ಕೇವಲ ಆಂತರಿಕ ಮೌಲ್ಯಗಳಿಗಾಗಿ ಎಕ್ಸ್ಟರ್ನಲ್-ಸ್ಟೋರ್ ಹೂಕ್ ಅನ್ನು ಬಳಸುವುದು ಅನಗತ್ಯ ಸಂಕೀರ್ಣತೆಯನ್ನು ಸೇರಿಸುತ್ತದೆ.
ಯಾವಾಗ useSyncExternalStore ಅನ್ನು ಬಳಸಬೇಕು
- ಬ್ರೌಸರ್ APIಗಳನ್ನು ಬಳಸುವಾಗ (window size, network-online status, media queries).
- React ಬಗ್ಗೆ ಅರಿವಿಲ್ಲದ ಪ್ಲೇನ್ JavaScript ಸ್ಟೋರ್ ಅನ್ನು ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ.
- Prop-drilling ಅನ್ನು ಅನೇಕ ಕಾಂಪೊನೆಂಟ್ಗಳು ಸಬ್ಸ್ಕ್ರೈಬ್ ಮಾಡುವ ಗ್ಲೋಬಲ್ ರೀಡ್-ಓನ್ಲಿ (read-only) ಮೂಲದಿಂದ ಬದಲಾಯಿಸುವಾಗ.
ವಿರೋಧಾತ್ಮಕ ವಾದ
useState + useEffect ಪದ್ಧತಿಯು ಸರಳವಾದ ಮತ್ತು ಅಪರೂಪವಾಗಿ ಬದಲಾಗುವ ಡೇಟಾಗೆ ಇಂದಿಗೂ ಕೆಲಸ ಮಾಡುತ್ತದೆ, ವಿಶೇಷವಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಕನ್ಕರೆಂಟ್ ಫೀಚರ್ಗಳನ್ನು ಬಳಸದಿದ್ದಾಗ. ಇದು ಕೆಳಮಟ್ಟದ (lower-level) ವಿಧಾನವಾಗಿದ್ದು, ಕೆಲವು ಡೆವಲಪರ್ಗಳಿಗೆ ಇದು ಸುಲಭವೆನಿಸಬಹುದು ಏಕೆಂದರೆ ಸಬ್ಸ್ಕ್ರಿಪ್ಷನ್ ಲಾಜಿಕ್ ಎಫೆಕ್ಟ್ನಲ್ಲಿ ಸ್ಪಷ್ಟವಾಗಿ ಇರುತ್ತದೆ. ಆದಾಗ್ಯೂ, ಕನ್ಕರೆಂಟ್ ರೆಂಡರಿಂಗ್ ಅನ್ನು ಆನ್ ಮಾಡಿದಾಗ "tearing" ಆಗುವ ಅಪಾಯವಿರುತ್ತದೆ. ಈಗಾಗಲೇ React 18 ರ ಹೊಸ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಬಳಸುತ್ತಿರುವ ಪ್ರಾಜೆಕ್ಟ್ಗಳಿಗೆ, useSyncExternalStore ನೀಡುವ ಹೆಚ್ಚಿನ ಸುರಕ್ಷತೆಯು ಸಣ್ಣ ಮಟ್ಟದ ಹೆಚ್ಚುವರಿ ಕೋಡ್ (boilerplate) ಗಿಂತ ಹೆಚ್ಚು ಪ್ರಯೋಜನಕಾರಿಯಾಗಿದೆ.
ಮುಂದೆ ಗಮನಿಸಬೇಕಾದವುಗಳು
- ನಿಮ್ಮ ಸ್ಟೋರ್ನ getSnapshot ಸ್ಥಿರವಾದ ರೆಫರೆನ್ಸ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ; ಡೆವಲಪ್ಮೆಂಟ್ ಸಮಯದಲ್ಲಿ ರೆಫರೆನ್ಸ್ ಅನ್ನು
console.logಮಾಡುವುದರಿಂದ ಆಕಸ್ಮಿಕವಾಗಿ ಆಬ್ಜೆಕ್ಟ್ ಮರುಸೃಷ್ಟಿಯಾಗುತ್ತಿದೆಯೇ ಎಂದು ತಿಳಿಯಬಹುದು. - ಸಬ್ಸ್ಕ್ರಿಪ್ಷನ್ ಫಂಕ್ಷನ್ ಅನ್ನು ಲೈಟ್ವೇಟ್ (lightweight) ಆಗಿಡಿ – ಭಾರೀ ಕೆಲಸಗಳು ಎಕ್ಸ್ಟರ್ನಲ್ ಮೂಲದ ಒಳಗೇ ನಡೆಯಬೇಕೇ ಹೊರತು, React ಗೆ ನೀಡುವ ಕಾಲ್ಬ್ಯಾಕ್ನಲ್ಲಿ ಅಲ್ಲ.
- ಯಾವುದೇ "tearing" ಕಾಣಿಸಿಕೊಳ್ಳದಂತೆ ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು React ನ ಕನ್ಕರೆಂಟ್ ಮೋಡ್ನಲ್ಲಿ (ಉದಾಹರಣೆಗೆ,
ReactDOM.createRootಜೊತೆಗೆactಬಳಸಿ) ಕಾಂಪೊನೆಂಟ್ಗಳನ್ನು ಪರೀಕ್ಷಿಸಿ.
ಲೈವ್ ಡೆಮೊವು ಈ ಹೂಕ್ ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ ಎಂಬುದನ್ನು ತೋರಿಸುತ್ತದೆ; ಇದು React ಹೊರಗಿರುವ ಸರಳ ಕೌಂಟರ್ ಅನ್ನು ಸಿಂಕ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ದೃಶ್ಯ ದೋಷಗಳಿಲ್ಲದೆ ಹಲವಾರು ಕಾಂಪೊನೆಂಟ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡುತ್ತದೆ. ಡೆಮೊ https://usesyncexternalstore.vercel.app/ ನಲ್ಲಿ ಲಭ್ಯವಿದೆ. ಇದರ ಸೋರ್ಸ್ ಕೋಡ್ GitHub ನಲ್ಲಿ ಲಭ್ಯವಿದೆ ಮತ್ತು ಹೆಚ್ಚಿನ ವಿವರವಾದ ಲೇಖನವು ಇದರ ಅನುಷ್ಠಾನದ (implementation) ವಿವರಗಳನ್ನು ವಿವರಿಸುತ್ತದೆ.
ಸಾರಾಂಶ: React ಯು UI ನ ಭಾಗಗಳನ್ನು ಕ್ರಮಬದ್ಧವಲ್ಲದ ರೀತಿಯಲ್ಲಿ ರೆಂಡರ್ ಮಾಡಬಹುದಾದ ಜಗತ್ತಿನಲ್ಲಿ, useSyncExternalStore ಎಂಬುದು ಎಕ್ಸ್ಟರ್ನಲ್ ಡೇಟಾ ಮತ್ತು ಕಾಂಪೊನೆಂಟ್ ರೆಂಡರಿಂಗ್ ನಡುವಿನ ವಿಶ್ವಾಸಾರ್ಹ ಸೇತುವೆಯಾಗಿದೆ. ಇದು ದೃಶ್ಯ ಸ್ಥಿರತೆಯನ್ನು ಕಾಪಾಡುತ್ತದೆ, ಗ್ಲೋಬಲ್ ಸ್ಟೋರ್ಗಳಿಗೆ ಹೊಂದಿಕೆಯಾಗುತ್ತದೆ ಮತ್ತು ಈಗಾಗಲೇ ಜನಪ್ರಿಯ ಸ್ಟೇಟ್-ಮ್ಯಾನೇಜ್ಮೆಂಟ್ ಲೈಬ್ರರಿಗಳಲ್ಲಿ ಅಳವಡಿಸಲಾಗಿದೆ. ಎಲ್ಲಿಯಾದರೂ non-React ಸ್ಟೇಟ್ ಅನ್ನು ಓದಬೇಕಾದಲ್ಲಿ ಇದನ್ನು ಬಳಸಿ ಮತ್ತು ಅದರ ಪೂರ್ಣ ಪ್ರಯೋಜನ ಪಡೆಯಲು ಸ್ನ್ಯಾಪ್ಶಾಟ್ಗಳನ್ನು ಚಿಕ್ಕದಾಗಿ ಮತ್ತು ಸ್ಥಿರವಾಗಿ ಇರಿಸಿ.
