Rules that manage React Native component usage patterns and platform-specific requirements, ensuring proper text wrapping and platform separation.
Enforces using platform-specific filenames when components contain Android or iOS specific code, promoting proper code organization and platform separation.
/**
* ESLint rule that enforces platform-specific components in appropriate files
* Ensures Android and iOS components are placed in correctly named files
*/
module.exports = {
meta: {
fixable: "code", // Supports auto-fixing in some scenarios
schema: [{
type: "object",
properties: {
androidPathRegex: {
type: "string" // Custom regex pattern for Android file paths
},
iosPathRegex: {
type: "string" // Custom regex pattern for iOS file paths
}
},
additionalProperties: false
}]
},
create: function(context) {
// Returns ESLint visitors object with:
// - VariableDeclarator: Tracks React component destructuring
// - ImportDeclaration: Tracks react-native imports with platform components
// - 'Program:exit': Reports platform-specific components in wrong files
}
};Configuration Examples:
// Default configuration (built-in patterns)
"react-native/split-platform-components": "error"
// Custom file patterns
"react-native/split-platform-components": ["error", {
"androidPathRegex": "\\.android\\.(js|ts|jsx|tsx)$",
"iosPathRegex": "\\.ios\\.(js|ts|jsx|tsx)$"
}]
// Custom patterns for different naming conventions
"react-native/split-platform-components": ["error", {
"androidPathRegex": "_android\\.(js|ts)$",
"iosPathRegex": "_ios\\.(js|ts)$"
}]Usage Examples:
// File: Button.js (would trigger the rule)
import { Platform, TouchableOpacityIOS, TouchableNativeFeedbackAndroid } from 'react-native';
// This should be split into platform-specific files
// File: Button.ios.js (correct)
import { TouchableOpacityIOS } from 'react-native';
export const PlatformButton = TouchableOpacityIOS;
// File: Button.android.js (correct)
import { TouchableNativeFeedbackAndroid } from 'react-native';
export const PlatformButton = TouchableNativeFeedbackAndroid;
// File: Button.js (shared code - acceptable)
import { View, Text } from 'react-native';Detects raw text outside of Text components, ensuring all text content is properly wrapped for React Native compatibility.
/**
* ESLint rule that detects raw text outside of Text components
* Ensures all text content is properly wrapped in React Native Text components
*/
module.exports = {
meta: {
schema: [{
type: "object",
properties: {
skip: {
type: "array",
items: {
type: "string" // Array of component names to skip validation for
}
}
},
additionalProperties: false
}]
},
create: function(context) {
// Returns ESLint visitors object with:
// - Literal: Analyzes string literals in JSX for raw text
// - JSXText: Analyzes JSX text nodes for raw text
// - TemplateLiteral: Analyzes template literals in JSX for raw text
}
};Configuration Examples:
// Default configuration
"react-native/no-raw-text": "error"
// Skip validation for custom text components
"react-native/no-raw-text": ["error", {
"skip": ["CustomText", "StyledText", "FormattedText"]
}]Usage Examples:
// These would trigger the rule
function BadComponent() {
return (
<View>
Hello World {/* Raw text - not allowed */}
<Text>Good text</Text>
{someCondition && "Conditional text"} {/* Raw string - not allowed */}
<View>
Some text here {/* Raw text in View - not allowed */}
</View>
</View>
);
}
// Correct usage
function GoodComponent() {
return (
<View>
<Text>Hello World</Text> {/* Properly wrapped */}
<Text>Good text</Text>
{someCondition && <Text>Conditional text</Text>} {/* Properly wrapped */}
<View>
<Text>Some text here</Text> {/* Properly wrapped */}
</View>
</View>
);
}
// With custom skip components
function ComponentWithCustomText() {
return (
<View>
<CustomText>
This text is allowed {/* Skipped due to configuration */}
</CustomText>
<StyledText>
This is also allowed {/* Skipped due to configuration */}
</StyledText>
</View>
);
}The no-raw-text rule includes several components that are allowed to contain raw text by default:
const defaultAllowedElements = [
'Text', // Standard React Native Text component
'TSpan', // SVG text element
'StyledText', // Common styled-components pattern
'Animated.Text' // Animated Text component
];// Error messages
"Android components should be placed in android files"
"IOS components should be placed in ios files"
"IOS and Android components can't be mixed" // When both are found in same file// Error format: "Raw text ({text}) cannot be used outside of a <Text> tag"
"Raw text (Hello World) cannot be used outside of a <Text> tag"
"Raw text (Click here) cannot be used outside of a <Text> tag"
// For whitespace-only content
"Whitespace(s) cannot be used outside of a <Text> tag"
// For template literals
"TemplateLiteral: ${variableName} cannot be used outside of a <Text> tag"// Recommended file structure
components/
├── Button/
│ ├── index.js // Platform selector or shared logic
│ ├── Button.ios.js // iOS-specific implementation
│ ├── Button.android.js // Android-specific implementation
│ └── Button.shared.js // Shared utilities and styles
// Platform selector pattern (index.js)
import { Platform } from 'react-native';
import ButtonIOS from './Button.ios';
import ButtonAndroid from './Button.android';
export default Platform.select({
ios: ButtonIOS,
android: ButtonAndroid,
});The rules automatically detect platform-specific components from common imports:
// Automatically detected as iOS-specific
import {
TouchableOpacityIOS,
ActionSheetIOS,
DatePickerIOS,
PickerIOS,
TabBarIOS,
NavigatorIOS
} from 'react-native';
// Automatically detected as Android-specific
import {
TouchableNativeFeedbackAndroid,
DrawerLayoutAndroid,
ProgressBarAndroid,
ToolbarAndroid,
ViewPagerAndroid
} from 'react-native';The no-raw-text rule supports various text component patterns:
// Standard patterns (all supported)
import { Text } from 'react-native';
import { Text as RNText } from 'react-native';
import { Animated } from 'react-native';
<Text>Standard text</Text>
<RNText>Aliased text</RNText>
<Animated.Text>Animated text</Animated.Text>
// Custom components via configuration
<CustomText>Custom wrapped text</CustomText>
<StyledText>Styled component text</StyledText>