I realized that you can check if the device is an iPad simply by using Platform from react-native. The complete solution is below:
expo-screen-orientation needs to be installed
expo install expo-screen-orientation
and imported like this:
import * as ScreenOrientation from 'expo-screen-orientation';
Also, Platform should be imported from react-native
import { Platform } from 'react-native';
After that, it's simply a matter of checking if the device is an iPad and if so unlock the orientation.
if (Platform.isPad) {
await ScreenOrientation.unlockAsync();
}
Note that changes will not be shown in the Expo app because that app has default orientation and it can't be locked (at least not on iOS).
Of course, in app.json the orientation should be set to 'portrait'
"expo": {
...
"orientation": "portrait",
...
}
Update: Tested on Expo 36.0.0 and ScreenOrientation.unlockAsync() is not supported. Worked after upgrading to 38.0.0. Tested on 39.0.0., 40.0.0 and it works fine as well.
Additional Setup For Bare Workflows
For bare workflows additional setup is required.
Follow this tutorial from expo. Try building the app. If it fails make sure the import they stated is the second line just after #import "AppDelegate.h"
You should use the first option from their tutorial:
UIViewController *rootViewController = [[EXScreenOrientationViewController alloc] init]; // The default screen orientation will be set to `portrait`.
Which will set the default orientation to portrait.
After that, you'll need to open your project in XCode and check that the app supports all four rotations

After that everything should work: App orientation is locked to portrait unless the person is on an iPad