# Component Definition

## Properties

Component properties which are functions responding to events generated by components
should be prefixed with `on` to clarify that they're responding to events:

**Bad**:

    <TrackComponent
        press={ () => alert('pressed!') }
    />
    
**Good**:
    
    <TrackComponent
        onPress={ () => alert('pressed!') }
    />
    
## Event Handling

Behavior which occurs as the result of an event generated by a component should be externalized
from the component itself in order to keep the component "dumb" as well as ensure reuse. For example,
it is better for a component to externalize an `onPress` callback than to have the component
manage the side effects that occur as a result of this directly.

**Bad**:

    const TrackComponent = ({ navigation }) => (
        <TouchableOpacity 
            onPress={ () => navigation.navigate('track') }
        >
            <View />
        </TouchableOpacity>
    );
    
**Good**:

    const TrackComponent = ({ onPress }) => (
        <TouchableOpacity
            onPress={ () => onPress() }
        >
            <View />
        </TouchableOpacity>
    );
    
    const TrackContainer = ({ navigation }) => (
        <TrackComponent
            onPress={ () => navigation.navigate('track') }
        />
    );

## File Structure

Component definition should adhere to the following folder structure:

    .
    ├── TrackComponent.js
    ├── __tests__
    │   ├── TrackComponent.spec.js
    │   └── __snapshots__
    │       └── TrackComponent.spec.js.snap
    ├── index.js
    └── styles.js
    
### `styles.js`

Style definition for components should be in a separate `styles.js` folder.

**Bad**:

`TrackComponent.js`:

    import React from 'react';
    import { StyleSheet, View } from 'react-native';
    
    const styles = StyleSheet.create({
        container: {
            flexDirection: 'column'
        }
    });
    
    const TrackComponent = () => (
        <View style={ styles.container } />
    );
    
    export default TrackComponent;
    
**Good**:

`styles.js`:

    import { StyleSheet } from 'react-native';
    
    const styles = StyleSheet.create({
        container: {
            flexDirection: 'column'
        }
    });
    
    export default styles;
    
`TrackComponent.js`:

    import React from 'react';
    import { View } from 'react-native';
    import styles from './styles';
    
    const TrackComponent = () => (
        <View style={ styles.container } />
    );
    
    export default TrackComponent;

### `index.js`

A lightweight `index.js` should be in the root of the component:

    import TrackComponent from './TrackComponent';
    
    export default TrackComponent;
    
Importing this component in other areas should reference the root component package,
and *not* the component file directly.

**Bad**:

    import TrackComponent from './src/components/TrackComponent/TrackComponent';

**Good**:

    import TrackComponent from './src/components/TrackComponent';

### `__snapshots__/`

All components should have at least one snapshot defined for a default/base state of the
component. See [testing](/docs/contributing/testing.md) guidelines for more information.
