React Native specific linting rules for ESLint providing comprehensive code quality enforcement for React Native development
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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>