Today, I will introduce several React hooks , which are not commonly used, but are very useful. useSyncExternalStore listen for external data changes external data sources need to provide a subscription function, and this function needs to return the method of unsubscribing import React from 'react'; import { store } from './store.js' export const App () { const data = useSyncExternalStore(store.subscribe, store.getData) return <> <button onClick={store.add}>add+</button> {data} </> } // store.js let conut = 0; let listeners = []; export const store = { add () { count ++; }, subscribe(listener) { listeners = [...listeners, listener]; return () => { listeners = listeners.filter(l => l !== listener); }; }, geetDate () { return count; } } useId generate globally unique ID, give up Math.random () bar import { useId } from 'react'; function App() { const uuid = useId(); return ( <>{uuid}</> ); } useLayoutEffect trigger before layout update import { useState, useRef, useLayoutEffect } from 'react'; function Tooltip() { const ref = useRef(null); const [tooltipHeight, setTooltipHeight] = useState(0); useLayoutEffect(() => { const { height } = ref.current.getBoundingClientRect(); setTooltipHeight(height); }, []); return <></> } useDeferredValue UI defer updates without handwritten anti-shake function import SearchResults from './SearchResults.js'; export default function App() { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); return ( <> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <SearchResults query={deferredQuery} /> </Suspense> </> ); } useReducer customize a lightweight redux const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count:…