The re-render model just doesn't quite fit with the way most JS libraries work. They hand you a class that you have to keep around. This can be solved with useState, but you have to use this weird construction `const [instance] = useState(() => new Whatever())`. Or even worse if the library needs an element to instantiate.
Then, you likely need some event listeners. They ended up not implementing useEvent, so this has to happen in useEffect. God forbid if you need to rebind the listener because a prop changes (possibly every rerender) or the library does something heavy on adding them.
Then, if a prop changes and you need to do something (like recenter a map), useEffect.
Occasionally you might want to reach for useSyncExternalStore but then get hit by the identity issue. The return value must be the same between renders or you end up with infinite rerenders. Many libraries just do `return { foo, bar}`. Not good enough for react.
Basically every JS library integration ends up with a thousand use effects, various useMemos (and useCallbacks) and I've never got (or seen) a satisfying result. There's always sync issues or too many rerenders or...