Components

Now here is an interesting problem; we have come across this great framework for making fast differences between the Virtual DOM and its native components. How do we tell React Native what UI to represent or when to change it? A React Native component is a simple, reusable, function-like object that enables us to describe the native mobile components we want to render. They will always contain properties, state, and a render method. Let's start really simple by creating our own component.

Creating your first component

Creating a new component in React Native will look similar to the following:

import React, {
  Text,
  View
  } from 'react-native';
class HelloComponent extends React.Component {
  render () {
    return (
    <View>
      <Text>Hello React</Text>
    <View>
  );
  }
}

Tip

Remember to import the React Native module. Here, we are using the ES6 import statement; it is similar to how the node require module works.

Wait a second… What are these weird XML elements doing in my JavaScript code? Facebook has created its own syntactic extension over JavaScript to describe React components. Here is the exact same code, but written in ordinary JavaScript:

var HelloComponent = React.createClass({displayName: "HelloComponent"}, render: function () {
  return (
    React.createElement(View, null,
      React.createElement(Text, null, "Hello React")
  )
));

While it is possible to write React Native applications only in JavaScript, the previous syntax includes many added benefits for the developer.

JSX

JavaScript XML (JSX) is an XML-like extension to the ECMAScript specification. It combines the component logic (JavaScript) and markup (DOM or Native UI) into a single file.

A JSX Element will take the following form:

var element = (
  <JSXElement>
    <SubJSXElement />
    <SubJSXElement />
    <SubJSXElement />
  <JSXElement />
);

The JSX specification also defines the following:

  • The JSX Elements can be either self-opening <JSXElement></JSXElement> or self-closing <JSXElement />.
  • Accept attributes as an expression {} or string "" <Component attr="attribute">. Expressions are JavaScript snippets.
  • The children elements can be text, expressions, or elements.

Note

What if you have more than one component or a list of components?

There can only be a single root element; it means that if you have multiple components, you must wrap them in a parent component.

This is cool! We have gone from a deeply nested and imperative JavaScript code to a declarative format that describes the exact elements that we want to see in our components. There is no separation of concerns since our logic is coupled with our markup, making the components easier to debug and test. Since you can always include the same component in multiple other components, there is no need to duplicate the code anyway.

Note that JSX is only meant to be used as a preprocessor and it is not recommended to transpile in your production build. More information on JSX can be found in the official React documentation https://facebook.github.io/react/docs/jsx-in-depth.html or in the official JSX Specification https://facebook.github.io/jsx/.

Back to our first component

There are a few things that we have overlooked in our component. View and Text are two of the many components provided by React Native to build a UI. These are not regular components that render in the JavaScript layer, they can map directly to their native container parts! The View component maps to UIView in IOS and android.view in Android, while Text is the generic component to display text on each platform respectively. View and Text support various functions, such as layouts, styling, and touch handling.

Displaying the same static text over and over is not very exciting. Let's extend this simple component and add some more functionalities.

Props and states

At this point, you may be wondering how React Native deals with component manipulation and communication as the number of components grows into a component hierarchy. A component hierarchy, similar to a tree, starts with a root component and can contain many children. React Native provides two methods of data passing; one for data-flow down the component hierarchy and another for maintaining internal state.

Props

How do the components in the same component hierarchy communicate with each other? Data is passed down through properties commonly known as props. Props are considered to be immutable by convention and should never be modified directly. To pass a prop into a component, just add a camel-cased attribute to the component:

<HelloComponent text="Hello React" />

Props can be accessed internally in the component through this.props:

import React, {
  Text,
  View
} from 'react-native';

class HelloComponent extends React.Component {
  render () {
    return (
      <View>
        <Text>{this.props.text}</Text>
      View>
    );
  }
}

Tip

What if I want to pass down a lot of props?

It is possible to pass an array of props to a component using the ES7 spread operator <HelloComponent {...props} />.

It is not always necessary to include props with a component, but if you require a default value for your props, you can assign the defaultProps object to the component's class constructor.

HelloComponent.defaultProps = {text: "Default Text!"};

Validating props

If you are planning to expose your component to the public, it makes sense to constrain the ways developers can use it. To enforce that your components are being used correctly, the PropTypes module can be used to validate any props passed in. In the event that a prop does not pass the propType validation, a warning is shown to the developer in the console. The PropTypes cover a wide range of JavaScript types and primitives, including nested objects. You can define propTypes on a component's class constructor:

HelloComponent.propTypes = {text: React.PropTypes.string};

For more information on propTypes, visit the Prop Validation section of React Docs https://facebook.github.io/react/docs/reusable-components.html.

State

So now we can pass in the data, but what if the data changes, then how can we display these changes to the user? Components can optionally contain state, a mutable and private set of data. State is a great way to keep track of user input, asynchronous requests, and events. Let's update our component with additional text when the user interacts with it:

import React, {
  Text,
  View,
  Component
  } from 'react-native';
  class HelloComponent extends React.Component{
    constructor (props) {
      super(props);
      this.state = {  // Set Initial State
      appendText: ''
    };
  }
  render () {
    return (
      <View>
        <Text onPress={() => setState({text: ' Native!'})}>{this.props.text + this.state.appendText}</Text>
        <View>
    );
  }
}

Touching the Text component will trigger the function in its onPress prop. We are taking advantage of the ES6 arrow syntax to include our functionality in line with the text component.

Note

Using the ES6 arrow syntax will automatically bind this to a function. For any non-arrow function, if you need access to this then you need to bind the value to the function in the props expression <Text onPress={this.myFunction.bind(this)}>.

The setState function will merge the object you pass into the first argument with the current state of the component. Calling setState will trigger a new render where, instead of being empty, this.state.appendText will append Native! to the value of text, which we originally passed in from props. The final result is "Hello React" + " Native!" to produce "Hello React Native!".

Never try and modify the value of this state on your own. Directly changing the state could result in data loss during the next setState call and it will not trigger another re-render.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.46.58