As a designer specialising in mobile apps, I have to say nothing still comes close to native codebase experience. Expo & RN is fantastic for MVP (and I've been a super early adopter of RN back in ~2014). But once you start building anything serious, you will very quickly start hitting the walls.
As an example, some time ago, it was impossible to implement those iOS large headers that shrink to small once you start scrolling. Even though they were de facto standard in iOS for years already. Also the heavy layering of modals introduced in mostly in iOS 15 were basically impossible. Plus they heavily rely on subtle transitions like the 2nd layer scaling down, moving back and top edge peeking out at the top, so that the user gets a hint where they are in the hierarchy... Not sure if all this stuff works now, but generally Expo & RN were very slow to catch up with iOS and you had to rely a lot on dubious libraries, ending up with messy patchwork.
All these minor details are extremely palpable, even by standard users, and the experience just always feels a bit off.
It’s possible to do all this stuff in RN - you just need good native bindings to the features
Stuff like the iOS 13 page sheet modals being broken is still an issue - but there’s a set of present/dismiss callbacks in the modal manager you can override in your code to fix it
Not sure if you meant page sheet controllers for iOS 15 (the ones that let you pin it half way up). There have been implementations of this, but they all suffered from a kind of crappy animation when you overstretched the page past its allowed limits. iOS would normally force a layout, then animate between the last layout and the new layout. But since RN’s layout is asynchronous, iOS couldn’t perform the animation and it looked sloppy
If asynchronous layout were the culprit, presumably that's the precise type of issue that react-native-reanimated solves? It seems to me that the experiences created via react-native-reanimated run quite smoothly indeed. Of course, the developer still has to reimplement interactions otherwise provided by iOS etc, but React Native should not be a reason for things like sloppy interactions.
The animated package doesn’t come into play here. When the layout needs to be recomputed in RN, it does it asynchronously - regardless of what’s calling it. Part of this can be explained because the JS can hook listen for layout updates via the onLayout prop and make changes to the layout - and could in theory cause infinite loops. But there’s no mechanism - as far as I’m aware - to say you don’t care about that detail and just do it synchronously anyway
I believe you're confusing react-native-reanimated (https://github.com/software-mansion/react-native-reanimated) with the Animated API from React Native. react-native-reanimated allows JS code to run on a UI thread that is able to synchronously modify layout, providing alternative synchronous ways for you to hook into the layouting. For instance, as opposed to the asynchronous `measure()` method provided by React Native to measure layouts, react-native-reanimated allows one to call their version of `measure()` (https://docs.swmansion.com/react-native-reanimated/docs/api/...) to perform the same operation on the UI thread, synchronously.
I meant both Animated APIs - neither is able to perform synchronous layouts - because react native is not able to do that. That’s the issue that’s stopping the page sheet controllers being added to react native. I actually was helping getting this added, but we never managed to get the layout issues fixed - https://github.com/facebook/react-native/pull/34834
The measure function you mention isn’t co-ordinated to the layout, so you could read it while a layout is pending and get old data - but that doesn't really matter for most cases
They keep saying you can do it - but I can’t actually see how. I don’t do a whole lot with the new architecture at the moment - it’s still very new and a very bumpy ride if you want to adopt it
One part of Expo's approach to UI is to create native user experiences. For several years Expo has invested in React Navigation and Expo Router, which use the system navigator. For instance, in iOS apps made with Expo in 2023, your headers will resize as the user scrolls and layered modals are natively supported. Details like showing the navigation stack when long-pressing the back arrow are supported from day one because Expo apps are native apps that use the system behavior.
In contrast, 2D UI frameworks like Flutter, Silverlight, and Flash replicate the system UI. In my experience it is possible to create a replica that visually looks like a pixel-perfect match but it is very difficult to make the replica behave the same, like the rendering the subtle layer transitions you talked about, invisible boundaries around gestures, and showing the navigation history stack. It is an uphill task and using the native system UI is a tailwind for Expo.
As an example, some time ago, it was impossible to implement those iOS large headers that shrink to small once you start scrolling. Even though they were de facto standard in iOS for years already. Also the heavy layering of modals introduced in mostly in iOS 15 were basically impossible. Plus they heavily rely on subtle transitions like the 2nd layer scaling down, moving back and top edge peeking out at the top, so that the user gets a hint where they are in the hierarchy... Not sure if all this stuff works now, but generally Expo & RN were very slow to catch up with iOS and you had to rely a lot on dubious libraries, ending up with messy patchwork.
All these minor details are extremely palpable, even by standard users, and the experience just always feels a bit off.