React Native Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

  1. In the root of our new app, we'll need to create a new Button folder for our reusable button-related code. Let's also create index.js and styles.js in our new Button folder.
  2. We will start by importing the dependencies for our new component. In the Button/index.js file, we will be creating a Button component. This means we'll need to import the Text and TouchableOpacity components. You'll notice we're also importing styles that do not exist yet. We will define these styles in a different file later in this recipe. In the Button/index.js file, we should have these imports:
import React, { Component } from 'react';

import {
Text,
TouchableOpacity,
} from 'react-native';

import {
Base,
Default,
Danger,
Info,
Success
} from './styles';
  1. Now that we have our dependencies imported, let's define the class for this component. We are going to need some properties and two methods. It's also required that we export this component so we can use it elsewhere:
export default class Button extends Component {
  getTheme() {
    // Defined in a later step
  }

  render() {
    // Defined in a later step
  }
}

  1. We need to select the styles to apply to our component based on the given properties. For this purpose, we will define the getTheme method. This method will check whether any of the properties are true and will return the appropriate styles. If none are true, it will return the Default style:
  getTheme() {
    const { danger, info, success } = this.properties;

    if (info) {
      return Info;
    }

    if (success) {
      return Success;
    }

    if (danger) {
      return Danger;
    }

    return Default;
  }
  1. It's required that all components have a render method. Here, we need to return the JSX elements for this component. In this case, we will get the styles for the given properties and apply them to the TouchableOpacity component.
    We are also defining a label for the button. Inside this label, we will render the children property. If a callback function is received, then it will be executed when the user presses this component:
  render() {
    const theme = this.getTheme();
    const {
      children,
      onPress,
      style,
      rounded,
    } = this.properties;

    return (
      <TouchableOpacity
        activeOpacity={0.8}
        style={[
          Base.main,
          theme.main,
          rounded ? Base.rounded : null ,
          style,
        ]}
        onPress={onPress}
      >
        <Text style={[Base.label, theme.label]}>{children}</Text>
      </TouchableOpacity>
    );
  }
  1. We are almost done with our Button component. We still need to define our styles, but first let's move over to the App.js file in the root of the project. We need to import the dependencies, including the Button component we have created.
    We are going to display an alert message when the user clicks the button, therefore, we also need to import the Alert component:
import React from 'react';
import {
  Alert,
  StyleSheet,
  View
} from 'react-native';
import Button from './Button';
  1. Once we have all the dependencies, let's define a stateless component that renders a few buttons. The first button will use the default style, and the second button will use the success style, which will add a nice green color to the button's background. The last button will display an alert when it gets pressed. For that, we need to define the callback function that will use the Alert component, just setting the title and message:
export default class App extends React.Component {
  handleButtonPress() {
    Alert.alert('Alert', 'You clicked this button!');
  }

  render() {
    return(
      <View style={styles.container}>
        <Button style={styles.button}>
          My first button
        </Button>
        <Button success style={styles.button}>
          Success button
        </Button>
        <Button info style={styles.button}>
          Info button
        </Button>
        <Button danger rounded style={styles.button}
        onPress={this.handleButtonPress}>
          Rounded button
        </Button>
      </View>
    );
  }
}
  1. We are going to add some styles for how the main layout should align and justify each button, along with some margins:
const styles = StyleSheet.create({
  container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
    },
  button: {
    margin: 10,
  },
});
  1. If we try to run the app now, we will get some errors. This is because we haven't declared the styles for our button. Let's work on that now. Inside the Button/styles.js file, we need to define the base styles. These styles will be applied to every instance of the button. Here, we will define a radius, padding, font color, and all the common styles that we need for this component:
import { StyleSheet } from 'react-native';

const Base = StyleSheet.create({
  main: {
    padding: 10,
    borderRadius: 3,
  },
  label: {
    color: '#fff',
  },
  rounded: {
    borderRadius: 20,
  },
});

  1. Once we have the common styles for our button, we need to define the styles for the Danger, Info, Success, and Default themes. For this, we are going to define different objects for each theme. Inside each theme, we will use the same object but with specific styles for that theme.
    To keep things simple, we are only going to change the backgroundColor, but we do have the option to use as many style properties as we want:
const Danger = StyleSheet.create({
  main: {
    backgroundColor: '#e74c3c',
  },
});

const Info = StyleSheet.create({
  main: {
    backgroundColor: '#3498db',
  },
});

const Success = StyleSheet.create({
  main: {
    backgroundColor: '#1abc9c',
  },
});

const Default = StyleSheet.create({
  main: {
    backgroundColor: 'rgba(0 ,0 ,0, 0)',
  },
  label: {
    color: '#333',
  },
});
  1. Finally, let's export the styles. This step is necessary so that the Button component can import all the styles for each theme:
export {
  Base,
  Danger,
  Info,
  Success,
  Default,
};
  1. If we open the app, we should be able to see our completed layout: