React Native Tutorial: Building Apps with JavaScript

Unfortunately Iā€™m having problems just with the Hello World app. Hereā€™s the code for it so far:

'use strict';

var React = require('react-native');
var styles = React.StyleSheet.create({
		text:
		{
			color: 'black',
			backgroundColor: 'white',
			fontSize: 30,
			margin: 80
		}
	});

class PropertyFinderApp extends React.Component {
	render() {
		return React.createElement(React.Text, {style: styles.text}, "Hello World!");
	}
}

React.AppRegistry.registerComponent('PropertyFinder', function()
{
	return PropertyFinderApp;
});

And hereā€™s the log from XCode:

2016-05-27 09:37:33.189 [fatal][tid:com.facebook.react.RCTExceptionsManagerQueue] Unhandled JS Exception: Super expression must either be null or a function, not undefined
2016-05-27 09:37:33.214 [error][tid:com.facebook.react.JavaScript] Module AppRegistry is not a registered callable module.
2016-05-27 09:37:33.215 [fatal][tid:com.facebook.react.RCTExceptionsManagerQueue] Unhandled JS Exception: Module AppRegistry is not a registered callable module.

I had the same problem. Something like this is what worked for me.

Replace this line:
var React = require(ā€˜react-nativeā€™);

With this:
import React, { Component } from ā€˜reactā€™;
import {
AppRegistry,
StyleSheet,
Text
} from ā€˜react-nativeā€™;

Removed ā€˜React.ā€™ prefix everywhere.

For example, instead of React.AppRegistry, just use AppRegistry.

2 Likes

I used the ā€œlatitudeā€ property.

Hi Chadrahder,

Replace it with the following code:

import React, { Component } from ā€˜reactā€™;
import {
AppRegistry,
StyleSheet,
Text,
View,
NavigatorIOS
} from ā€˜react-nativeā€™;

var styles = StyleSheet.create({
text:
{
color: ā€˜blackā€™,
backgroundColor: ā€˜whiteā€™,
fontSize: 30,
margin: 80
}
});

class PropertyFinderApp extends Component {
render() {
return ā€œHello Worldā€
}
}

AppRegistry.registerComponent(ā€˜PropertyFinderā€™, function()
{
return PropertyFinderApp;
});

2 Likes

If you are having problems with searching by location, try toggling the location in the Simulator:

  1. Select Debug > Location > None
  2. Select Debug > Location > Custom Locationā€¦
  3. Enter coordinates and click OK.
    This resolved the issue for me.

Thank you to everyone who answered my question. That certainly got things going. This is a great tutorial @tomelliott it would be great to see it updated because IMO it is invaluable ā€“ great work :slight_smile:

It seems as though some people have noticed that when you press to view a second property after you have already viewed another one, the first one you viewed is loaded instead of the one you pressed.

As has been pointed out elsewhere this is because the API no longer seems to return a guid field for each record.

The other key we can use then is rowID.

Iā€™m not sure I fully understand what the rowHasChanged function is doing and I canā€™t see it being called, but a good way to compare these is as follows:

var dataSource = new ListView.DataSource({
    rowHasChanged: (r1, r2) => this.props.listings.indexOf(r1) !== this.props.listings.indexOf(r2)
});

This should get the index of each row from the listings prop.

So far so goodā€¦ renderRow already has a rowID for each row so we can pass that into our onPress method:

onPress={() => this.rowPressed(rowID)}

And the rowPressed method itself just becomes:

rowPressed(rowID)
{
	var property = this.props.listings[rowID];

	...
}

This works for me :slight_smile:

Hope it helps!

Anyone got any tips for porting the same project to Android? Specifically it would need to use Navigator instead of NavigatorIOS and aside from the loading indicator (which is simple) thereā€™s not much else therefore it should be simple but Navigator seems slightly complicated.

Iā€™ve got it working so the SearchPage component loads but when I click Go I get an error related to this.props.navigator.

Great stuff, and it all works!
(with minor changes for react-native 0.27.0-rc2)

As people already suggested namespaces have changed for ā€˜reactā€™ and ā€˜react-nativeā€™. I like Tomā€™s approach require(ā€˜ā€¦ā€™) so my fix in index.ios.js is like this:

ā€˜use strictā€™;
var React = require(ā€˜reactā€™);
var ReactNative = require(ā€˜react-nativeā€™);

Youā€™ll need to figure out after that which components is in which namespace. However the following destructive syntax taken from my modified SearchResult.js can help:

ā€˜use strictā€™;
var React = require(ā€˜reactā€™);
var {
Component
} = React;

var ReactNative = require(ā€˜react-nativeā€™);
var {
StyleSheet,
Text,
View,
TouchableHighlight,
Image,
ListView
} = ReactNative;

And lastly the guid property is no longer supported by the Nestoria api (or at least i didnā€™t see it :slight_smile:) , but you can use thumb_url for the uniqueness purpose. So youā€™ll need to replace ALL occurrences of guid with thumb_url in SearchResults.js, e.g. replace:

var property = this.props.listings.filter(prop => prop.guid === guid)[0];

with:

var property = this.props.listings.filter(prop => prop.thumb_url === thumbUrl)[0];

Thank you for the great tutorial!
Tom, great references as well, which is extremely useful!!

1 Like

This is very useful, thanks.

Do you think there are any problems with the approach I recommended which uses the index within the property list array?

Not really, it will work as well. However you are bound to the row index which may change if some sorting/filtering is applied to the list. You can fix that by reindexing after such operation is applied. Binding to unique data property have more chances to succeed - however if they change the API again it will fail too :wink:, so nothing is perfect!

1 Like

Great point, thank you.

I considered seeing if it was possible to generate a hash of a object and use that, but it didnā€™t seem straight forward. I think your solution, all things considered is better.

Someone above recommended the latitude property, but I think this is potentially not ideal in case there are several entries that might have the same latitude for some reason.

Great tutorial. I can confirm the issues (and fixes) regarding GUID. One thing, which is not working well is the behavior of the app on change of orientation. In landscape things are not rendered correctly.

I tried doing the tutorial with my best abilities since Iā€™m really new to React Native (or React development in general) and I was wondering if anyone else is having a problem with the information when going into property view? It seems like its only generating the first data when going to any of the property list.

How do I pass the information from this SearchResults.js

  constructor(props) {
    super(props);
    var dataSource = new ListView.DataSource(
      {rowHasChanged: (r1, r2) => r1.guid !== r2.guid});
    this.state = {
      dataSource: dataSource.cloneWithRows(this.props.listings)
    };
  }

into PropertyView.js

On the initial build, i.e. after running this line:

react-native init PropertyFinder

I get the white PropertyFinder screen. However, a few seconds later it refreshes and I get a red screen with the following errors:

Unable to execute JS call: __fbBatchedBridge is undefined

Has something changed? All Iā€™m doing is creating a bare bones project and running it.

Iā€™m not very well in english, perhaps thatā€™s why I canā€™t understand what does this part means: ā€œUI is simply expressed as a function of the current application stateā€. Could you give some more words on that?
Isnā€™t any UI is the function of the current applications state? Itā€™s not the picture after all. If so, then itā€™s not the advantage.

Hi ahliu1, I had the same problem and I realised that ā€˜guidā€™ is not present on the response json. My fix was to use ā€˜titleā€™ instead to check which row you pressed:

Inside the renderRow method in SearchResults.js replace guid with title:

return ( <TouchableHighlight onPress={() => this.rowPressed(rowData.title)}
and inside the filter method of rowPressed too:

rowPressed(propertyTitle) { var property = this.props.listings.filter(prop => prop.title === propertyTitle)[0];

I hope that helps :slight_smile:

Any chance this tutorial could be updated for 0.28? It no longer works with the new syntax.

hi mttmanzo I have the same problem here, and I canā€™t resolve it, but I wonder if the writer missed some instructions above, for example in render of SearchPage.js , onPress function is not defined also for SearchResults.js as you have mentionned before!!!

If you can please help me to fix it.
Tanks !

Hi imano, let me show where in the tutorial you can find the implementation on onPress for SearchPage and for SearchResults:

SearchPage, chapter Initiating a Search:

if you see, Tom asks you to implement onPress within the TouchableHighlight tag that renders the ā€˜Goā€™ text.

Instead, in the SearchResults, the implementation is here:

Now, if you want to follow my fix, you just have to replace guid with text.

Let me know and good luck!

Matteo