React Native configuration extends the ESNext base configuration with React and React Native specific linting rules. It provides comprehensive coverage for mobile application development using React Native, including React component best practices and React Native platform-specific rules.
React Native-specific ESLint configuration that extends ESNext with React and React Native rules.
/**
* React Native ESLint configuration
* Accessible as: "react-native" or "recommended/react-native"
*/
env:
browser: true # Enable browser-like globals for React Native
plugins:
- react # React-specific linting rules
- react-native # React Native-specific linting rules
extends:
- esnext # Inherit all ESNext rules and configuration
- plugin:react/recommended # React recommended rulesEnvironment Settings:
browser: true: Enables browser-like global variables that are available in React Native:
console, setTimeout, setInterval, clearTimeout, clearIntervalfetch, FormData, XMLHttpRequest (via polyfills)Plugin Configuration:
react: Provides React-specific linting rules for component developmentreact-native: Provides React Native platform-specific linting rulesExtended Configurations:
esnext: Inherits all rules from eslint-config-esnextplugin:react/recommended: Includes essential React linting rulesRules that address React Native development patterns and platform-specific best practices.
/**
* React Native-specific linting rules
*/
rules: {
// React Native plugin rules
"react-native/no-color-literals": "error", // Require color constants instead of literals
"react-native/no-inline-styles": "error", // Disallow inline styles
"react-native/no-unused-styles": "error", // Disallow unused StyleSheet styles
"react-native/split-platform-components": "error", // Require platform-specific file extensions
// React component rules
"react/jsx-boolean-value": "error", // Enforce boolean attribute notation
"react/jsx-handler-names": "error", // Enforce event handler naming conventions
"react/jsx-key": "warn", // Warn on missing key prop in lists
"react/jsx-no-bind": "warn", // Warn on bind() in JSX props
"react/jsx-pascal-case": "error", // Enforce PascalCase for component names
"react/jsx-wrap-multilines": "error", // Require parentheses around multiline JSX
"react/no-danger": "error", // Disallow dangerouslySetInnerHTML
"react/no-did-mount-set-state": "error", // Disallow setState in componentDidMount
"react/no-did-update-set-state": "error", // Disallow setState in componentDidUpdate
"react/no-find-dom-node": "error", // Disallow findDOMNode
"react/no-multi-comp": ["error", { "ignoreStateless": true }], // Disallow multiple components per file
"react/no-render-return-value": "error", // Disallow using ReactDOM.render return value
"react/no-string-refs": "error", // Disallow string refs
"react/no-unused-prop-types": "error", // Disallow unused prop types
"react/prefer-es6-class": "error", // Prefer ES6 class components
"react/prefer-stateless-function": "error" // Prefer stateless functional components
}# .eslintrc.yaml
extends:
- react-native
# Optional app-specific rules
rules:
no-console: warn# .eslintrc.yaml
extends:
- react-native
parser: '@typescript-eslint/parser'
plugins:
- '@typescript-eslint'
rules:
# TypeScript-specific overrides
no-unused-vars: off
'@typescript-eslint/no-unused-vars': error# .eslintrc.yaml
extends:
- react-native
rules:
# Stricter rules for production
no-console: error
no-debugger: error
react-native/no-inline-styles: error
# Performance optimizations
react/jsx-no-bind: error
react/no-multi-comp: error# .eslintrc.yaml
extends:
- react-native
overrides:
# Test files
- files: ['**/__tests__/**', '**/*.test.{js,jsx}', '**/*.spec.{js,jsx}']
env:
jest: true
rules:
react/prop-types: off
react-native/no-inline-styles: offRequires using color constants instead of hard-coded color values for maintainability.
// ❌ Error: Hard-coded color literals
const styles = StyleSheet.create({
container: {
backgroundColor: '#FF0000',
borderColor: 'red',
},
text: {
color: '#333333'
}
});
// ✅ Correct: Use color constants
const Colors = {
RED: '#FF0000',
DARK_GRAY: '#333333',
WHITE: '#FFFFFF'
};
const styles = StyleSheet.create({
container: {
backgroundColor: Colors.RED,
borderColor: Colors.RED,
},
text: {
color: Colors.DARK_GRAY
}
});Requires using StyleSheet instead of inline styles for performance and maintainability.
// ❌ Error: Inline styles
function MyComponent() {
return (
<View style={{ backgroundColor: 'red', padding: 10 }}>
<Text style={{ fontSize: 16, color: 'white' }}>
Hello World
</Text>
</View>
);
}
// ✅ Correct: StyleSheet styles
const styles = StyleSheet.create({
container: {
backgroundColor: 'red',
padding: 10,
},
text: {
fontSize: 16,
color: 'white',
}
});
function MyComponent() {
return (
<View style={styles.container}>
<Text style={styles.text}>
Hello World
</Text>
</View>
);
}Prevents unused styles in StyleSheet declarations.
// ❌ Error: Unused styles
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
fontSize: 20, // This style is never used
},
text: {
color: 'blue',
}
});
function MyComponent() {
return (
<View style={styles.container}>
<Text style={styles.text}>Hello</Text>
</View>
);
}
// ✅ Correct: Remove unused styles
const styles = StyleSheet.create({
container: {
flex: 1,
},
text: {
color: 'blue',
}
});Requires platform-specific file extensions for platform-specific components.
// ❌ Error: Platform-specific code in single file
import { Platform } from 'react-native';
export function PlatformComponent() {
if (Platform.OS === 'ios') {
return <IOSSpecificComponent />;
} else {
return <AndroidSpecificComponent />;
}
}
// ✅ Correct: Split into platform files
// PlatformComponent.ios.js
export function PlatformComponent() {
return <IOSSpecificComponent />;
}
// PlatformComponent.android.js
export function PlatformComponent() {
return <AndroidSpecificComponent />;
}
// Usage automatically selects correct file
import { PlatformComponent } from './PlatformComponent';Warns against creating functions in render method which can impact performance.
// ⚠️ Warning: Function creation in render
class MyComponent extends Component {
render() {
return (
<FlatList
data={this.props.items}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => this.handlePress(item)}>
<Text>{item.name}</Text>
</TouchableOpacity>
)}
/>
);
}
}
// ✅ Better: Use bound methods or useCallback
class MyComponent extends Component {
handlePress = (item) => {
// Handle press
}
renderItem = ({ item }) => (
<TouchableOpacity onPress={() => this.handlePress(item)}>
<Text>{item.name}</Text>
</TouchableOpacity>
)
render() {
return (
<FlatList
data={this.props.items}
renderItem={this.renderItem}
/>
);
}
}
// ✅ With hooks: Use useCallback
function MyComponent({ items }) {
const handlePress = useCallback((item) => {
// Handle press
}, []);
const renderItem = useCallback(({ item }) => (
<TouchableOpacity onPress={() => handlePress(item)}>
<Text>{item.name}</Text>
</TouchableOpacity>
), [handlePress]);
return (
<FlatList
data={items}
renderItem={renderItem}
/>
);
}Warns about missing key props in list items.
// ⚠️ Warning: Missing key prop
function ItemList({ items }) {
return (
<View>
{items.map(item => (
<Text>{item.name}</Text> // Missing key
))}
</View>
);
}
// ✅ Correct: Add key prop
function ItemList({ items }) {
return (
<View>
{items.map(item => (
<Text key={item.id}>{item.name}</Text>
))}
</View>
);
}// ✅ Recommended component structure
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import PropTypes from 'prop-types';
function MyComponent({ title, onPress, disabled }) {
const [isPressed, setIsPressed] = useState(false);
useEffect(() => {
// Component effects
}, []);
return (
<TouchableOpacity
style={[styles.container, disabled && styles.disabled]}
onPress={onPress}
disabled={disabled}
>
<Text style={styles.title}>{title}</Text>
</TouchableOpacity>
);
}
MyComponent.propTypes = {
title: PropTypes.string.isRequired,
onPress: PropTypes.func,
disabled: PropTypes.bool,
};
MyComponent.defaultProps = {
onPress: undefined,
disabled: false,
};
const styles = StyleSheet.create({
container: {
padding: 16,
backgroundColor: '#007AFF',
borderRadius: 8,
},
disabled: {
opacity: 0.5,
},
title: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
});
export default MyComponent;// ✅ Optimized FlatList implementation
import React, { memo, useCallback } from 'react';
import { FlatList } from 'react-native';
const ListItem = memo(({ item, onPress }) => (
<TouchableOpacity onPress={() => onPress(item)}>
<Text>{item.name}</Text>
</TouchableOpacity>
));
function MyList({ data, onItemPress }) {
const renderItem = useCallback(({ item }) => (
<ListItem item={item} onPress={onItemPress} />
), [onItemPress]);
const keyExtractor = useCallback((item) => item.id, []);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
/>
);
}Inherited from ESNext:
babel-eslint: ^10.0.1 - Parser for modern JavaScript syntaxeslint: ^6.8.0 - ESLint coreeslint-plugin-babel: ^5.2.1 - Babel-specific ESLint ruleseslint-plugin-import: ^2.14.0 - Import/export validation rulesAdditional Dependencies:
eslint-config-esnext: ^4.1.0 - Base ESNext configurationeslint-plugin-react: ^7.19.0 - React-specific linting ruleseslint-plugin-react-native: ^3.8.1 - React Native-specific linting rulesPeer Dependencies:
eslint: ^6.0.0 - Required ESLint version for consuming projectsnpm install --save-dev eslint-config-recommended# .eslintrc.yaml
extends:
- recommended/react-nativenpm install --save-dev eslint-config-react-native# .eslintrc.yaml
extends:
- react-native