When building interactive UIs with forms and dynamic components, focus management is critical—not just for UX, but also for accessibility and keyboard navigation.
Good focus management ensures:
function MyComponent() {const inputRef = useRef<HTMLInputElement>(null)const [show, setShow] = useState(false)return (<div><buttononClick={() => {setShow(true)inputRef.current?.focus()}}>Show</button>{show && <input ref={inputRef} />}</div>)}
You expect the input to receive focus when it appears — but it doesn’t.
Because React batches state updates, the DOM is not updated immediately after calling setShow(true).
flushSyncimport { flushSync } from 'react-dom'function MyComponent() {const inputRef = useRef<HTMLInputElement>(null)const [show, setShow] = useState(false)return (<div><buttononClick={() => {flushSync(() => setShow(true))inputRef.current?.focus()}}>Show</button>{show && <input ref={inputRef} />}</div>)}
flushSync forces React to commit the DOM update synchronously, so the input exists when focus() is called.
⚠️ Use sparingly —
flushSyncis a performance trade-off and should only be used for UX-critical cases like focus management.
ref + focus() to control focus explicitlyuseEffect when focus isn’t urgentflushSync only when DOM must update synchronously