Expo announced SDK 56, which introduces the useNativeState hook in Expo UI. It's worth understanding from the ground up, because it unlocks real performance wins in places where React state has always felt slow.
In short: useNativeState creates a lightweight reference (like a pointer or ID) to a value that lives in native memory and is shared with the SwiftUI/Compose UI thread, so the native UI can read and write it without involving the JS thread at all.
The problem with controlled state
Let's see it in action. The following example uses a normal useState to get text from a TextField, the classic "controlled React state" pattern that everyone has hated ever since Dan Abramov posted about it on X.
Inkigo AI using a TextField with controlled React state
The app in the demos is Inkigo, my AI tattoo app on the App Store. Notice how the UI becomes unresponsive and laggy as I spam the autocomplete.
This happens because every keystroke writes a new value into React state, which re-renders the component:
- Native
TextField sends an event to the JS thread with the new text value.
- The JS thread updates the React state with that value.
- The component re-renders and
TextField receives a new prop with the updated value.
- The native
TextField has to process this new prop and update the UI accordingly.
Four steps, every keystroke. That's why fast typing feels like wading through mud.
Enter useNativeState
Let's see how this works with useNativeState instead.
Inkigo AI using a TextField with native state
Notice how smooth it is. I was tapping as fast as I could and couldn't make it lag at all. I almost lost a finger trying.
So why does this work so nicely?