or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

esnext.mdindex.mdnode.mdreact-native.mdstyle-guides.md
tile.json

react-native.mddocs/

React Native Configuration

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.

Capabilities

Base React Native Configuration

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 rules

Environment Settings:

  • browser: true: Enables browser-like global variables that are available in React Native:
    • console, setTimeout, setInterval, clearTimeout, clearInterval
    • fetch, FormData, XMLHttpRequest (via polyfills)
    • Global object references used by React Native

Plugin Configuration:

  • react: Provides React-specific linting rules for component development
  • react-native: Provides React Native platform-specific linting rules

Extended Configurations:

  • esnext: Inherits all rules from eslint-config-esnext
  • plugin:react/recommended: Includes essential React linting rules

React Native Specific Rules

Rules 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
}

Usage Examples

Basic React Native App

# .eslintrc.yaml
extends:
  - react-native

# Optional app-specific rules
rules:
  no-console: warn

React Native with TypeScript

# .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

React Native Production Build

# .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

React Native with Testing

# .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: off

Rule Violations and Solutions

react-native/no-color-literals

Requires 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
  }
});

react-native/no-inline-styles

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>
  );
}

react-native/no-unused-styles

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',
  }
});

react-native/split-platform-components

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';

react/jsx-no-bind

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}
    />
  );
}

react/jsx-key

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>
  );
}

React Native Best Practices

Component Structure

// ✅ 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;

Performance Patterns

// ✅ 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}
    />
  );
}

Dependencies

Inherited from ESNext:

  • babel-eslint: ^10.0.1 - Parser for modern JavaScript syntax
  • eslint: ^6.8.0 - ESLint core
  • eslint-plugin-babel: ^5.2.1 - Babel-specific ESLint rules
  • eslint-plugin-import: ^2.14.0 - Import/export validation rules

Additional Dependencies:

  • eslint-config-esnext: ^4.1.0 - Base ESNext configuration
  • eslint-plugin-react: ^7.19.0 - React-specific linting rules
  • eslint-plugin-react-native: ^3.8.1 - React Native-specific linting rules

Peer Dependencies:

  • eslint: ^6.0.0 - Required ESLint version for consuming projects

Installation

As Part of Recommended Package

npm install --save-dev eslint-config-recommended
# .eslintrc.yaml
extends:
  - recommended/react-native

As Standalone Package

npm install --save-dev eslint-config-react-native
# .eslintrc.yaml
extends:
  - react-native