React Native Tutorial: Building iOS Apps with JavaScript
In this React Native tutorial you’ll learn how to build native iOS and Android apps based on the hugely popular React JavaScript library. By Christine Abernathy.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
React Native Tutorial: Building iOS Apps with JavaScript
40 mins
Handling Assets
The final step to complete the search screen of the application is to add the house graphic. Download and unzip the images zip file.
Next, create a directory in your root project folder and call it Resources. Place the three images of the house in this directory.
Asset Catalogs: Apple recommends placing images in Asset Catalogs where possible. In React Native, however, it’s recommended not to. Placing your assets alongside your components helps to keep your components self contained, doesn’t require the app to be relaunched if you add new images. It also provides a single place for adding images if you are building for both iOS and Android.
Asset Catalogs: Apple recommends placing images in Asset Catalogs where possible. In React Native, however, it’s recommended not to. Placing your assets alongside your components helps to keep your components self contained, doesn’t require the app to be relaunched if you add new images. It also provides a single place for adding images if you are building for both iOS and Android.
Back in SearchPage.js, add the following beneath the closing tag of the View
component that wraps the text input and button:
<Image source={require('./Resources/house.png')} style={styles.image}/>
Now, add the image’s corresponding style to the end of the style list:
image: {
width: 217,
height: 138,
},
Save your changes and check out your new UI:
react-native start
command you have in the terminal).Your current app looks good, but it’s somewhat lacking in functionality. Your task now is to add some state to your app and perform some actions.
Adding Component State
A React component can manage its internal state through an object called, you guessed it, state
. Whenever a component’s state changes, render()
is called.
Within SearchPage.js, add the following code just before render()
:
constructor(props) {
super(props);
this.state = {
searchString: 'london'
};
}
Your component now has a state
variable, with searchString
set to an initial value of london
.
Within render()
, change TextInput
to the following:
<TextInput
style={styles.searchInput}
value={this.state.searchString}
placeholder='Search via name or postcode'/>
This sets the TextInput
value property — that is, the text displayed to the user — to the current value of the searchString
state variable. This takes care of setting the initial state, but what happens when the user edits this text?
The first step is to create a method that acts as an event handler. Within the SearchPage
class add the following method below the constructor
:
_onSearchTextChanged = (event) => {
console.log('_onSearchTextChanged');
this.setState({ searchString: event.nativeEvent.text });
console.log('Current: '+this.state.searchString+', Next: '+event.nativeEvent.text);
};
This defines a function using the =>
syntax. This is an arrow function, another recent addition to the JavaScript language that provides a succinct syntax for creating anonymous functions.
The function takes the value from the native browser event’s text
property and uses it to update the component’s state. It also adds some logging code that will make sense shortly.
Note: JavaScript classes do not have access modifiers, so they have no concept of private
. As a result you often see developers prefixing methods with an underscore to indicate that they should be considered private.
Note: JavaScript classes do not have access modifiers, so they have no concept of private
. As a result you often see developers prefixing methods with an underscore to indicate that they should be considered private.
To wire up this method so it gets called when the text changes, return to the TextInput
field within the render
method and add an onChange
property so the tag looks like the following:
<TextInput
style={styles.searchInput}
value={this.state.searchString}
onChange={this._onSearchTextChanged}
placeholder='Search via name or postcode'/>
Whenever the user changes the text, you invoke the function supplied to onChange
; in this case, it’s _onSearchTextChanged
.
There’s one final step before you refresh your app again: add the following logging statement to the top of render()
, just before return
:
console.log('SearchPage.render');
Save your changes and return to your simulator.
You should see the text input’s initial value set to london. You should also see Xcode console logs when editing the text:
2017-11-26 23:00:31.847 [info][tid:com.facebook.react.JavaScript] SearchPage.render
2017-11-26 23:00:38.134 [info][tid:com.facebook.react.JavaScript] _onSearchTextChanged
2017-11-26 23:00:38.134 [info][tid:com.facebook.react.JavaScript] Current: london, Next: londona
2017-11-26 23:00:38.135 [info][tid:com.facebook.react.JavaScript] SearchPage.render
Looking at the console logs, the order of the logging statement seems a little odd:
- This is the initial call to
render()
to set up the view. - You invoke
_onSearchTextChanged()
when the text changes. - You call
this.setState()
to schedule an update to the component state to reflect the new input text. This triggers another render. - You log the current and the next search text values.
Note: You may see frequent log messages related to nw_connection_get_connected_socket
or finished with error - code : -1001
. These are due to attempted connections to the React debugging tools. Silence these temporarily by going to Product \ Scheme \ Edit Scheme and finding the Arguments tab of the Run config. Add a new environment variable called OS_ACTIVITY_MODE
with the value disable
.
Build and run the project for the settings to take effect.
Note: You may see frequent log messages related to nw_connection_get_connected_socket
or finished with error - code : -1001
. These are due to attempted connections to the React debugging tools. Silence these temporarily by going to Product \ Scheme \ Edit Scheme and finding the Arguments tab of the Run config. Add a new environment variable called OS_ACTIVITY_MODE
with the value disable
.
Build and run the project for the settings to take effect.
A React component state change triggers a UI update. This de-couples the rendering logic from state changes affecting the UI. Most other UI frameworks put the onus on you to update the UI based on state changes. Alternatively, the updates are done through an implicit link between the state and UI. For an example of the latter, see this article on implementing the MVVM pattern with ReactiveCocoa.
At this point you’ve probably spotted a fundamental flaw in this concept. Yes, that’s right — performance!
Surely you can’t just throw away your entire UI and re-build it every time something changes? This is where React gets really smart.
Each time the UI renders itself, it takes the view tree returned by your render methods, and reconciles — or diffs — it with the current UIKit view. The output of this reconciliation process is a simple list of updates that React needs to apply to the current view. That means only the things that have actually changed will re-render!
You can wrap your head around all that later; you still have some work to do in the app.