Inline check (Platform.OS / Platform.select) dùng cho khác biệt nhỏ trong cùng một component:
const styles = StyleSheet.create({
shadow: Platform.select({
ios: { shadowColor: '#000', shadowOpacity: 0.2, shadowRadius: 4 },
android: { elevation: 4 },
}),
})Tách file (Component.ios.tsx + Component.android.tsx) dùng khi:
- Code khác biệt nhiều (>30%) — vd map view dùng react-native-maps iOS gọi Apple Maps, Android gọi Google Maps qua key khác.
- Native module chỉ tồn tại một bên.
- Performance: tránh ship code không dùng — Metro bundler tự pick .ios.tsx cho iOS, .android.tsx cho Android, code platform khác không vào bundle.
Trade-off: tách file khó maintain (logic share phải extract ra Component.shared.ts), nên chỉ tách khi thật sự cần. Còn Platform.OS === 'ios' rải rác hơn 5–6 chỗ trong file thì chính là tín hiệu nên tách.
Inline checks (Platform.OS / Platform.select) are for small differences within one component:
const styles = StyleSheet.create({
shadow: Platform.select({
ios: { shadowColor: '#000', shadowOpacity: 0.2, shadowRadius: 4 },
android: { elevation: 4 },
}),
})Split files (Component.ios.tsx + Component.android.tsx) when:
- The code differs significantly (>30%) — e.g. a map view that uses react-native-maps against Apple Maps on iOS and Google Maps on Android with different keys.
- A native module exists on only one platform.
- Performance: avoid shipping unused code — Metro picks .ios.tsx for iOS and .android.tsx for Android, the other platform's code does not enter the bundle.
Trade-off: splitting hurts maintainability (shared logic must be extracted to Component.shared.ts), so split only when it pays off. If you have 5–6 Platform.OS === 'ios' checks scattered in one file, that is the signal to split.