Skip to content

Commit 41453a5

Browse files
committed
Finish tutorial draft
1 parent b900ce2 commit 41453a5

File tree

6 files changed

+201
-10
lines changed

6 files changed

+201
-10
lines changed

Examples/Movies/SearchScreen.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ var TimerMixin = require('react-timer-mixin');
2525
var MovieCell = require('./MovieCell');
2626
var MovieScreen = require('./MovieScreen');
2727

28-
var fetch = require('fetch');
29-
3028
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/';
3129
var API_KEYS = ['7waqfqbprs7pajbz28mqf6vz', 'y4vwv8m33hed9ety83jmv52f'];
3230

docs/Tutorial.md

Lines changed: 201 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ next: videos
1111

1212
This is a tutorial that aims to get you up to speed with writing iOS apps using React Native. If you want to learn what React Native is and why Facebook built it, check out this blog post: **[INSERT BLOG POST URL]**.
1313

14-
We assume you have experience writing websites with ReactJS. If not, you can learn about ReactJS [here](http://facebook.github.io/react/).
14+
We assume you have experience writing websites with React. If not, you can learn about React [here](http://facebook.github.io/react/).
1515

1616

1717
## Setup
@@ -109,6 +109,10 @@ And lastly we need to apply this still to the Image component:
109109

110110
Press cmd+R and the image should now render.
111111

112+
Screenshot:
113+
114+
<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialMock.png" alt="screenshot" width="320px" />
115+
112116

113117
### Add some styling
114118

@@ -178,15 +182,13 @@ This is pretty straightforward if you've ever seen CSS before. Make the title la
178182

179183
Go ahead and press cmd+R and you'll see the updated view.
180184

181-
### Fetching real data
185+
Screenshot:
182186

183-
Fetching data from Rotten Tomatoes's API isn't really relevant to learning React Native so feel free to breeze through this section.
187+
<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialStyledMock.png" alt="screenshot" width="320px" />
184188

185-
Require the fetch module which is used to make an HTTP request to rotten tomatoes's API.
189+
### Fetching real data
186190

187-
```javascript
188-
var fetch = require('fetch');
189-
```
191+
Fetching data from Rotten Tomatoes's API isn't really relevant to learning React Native so feel free to breeze through this section.
190192

191193
Add the following constants to the top of the file (typically below the requires) to create the REQUEST_URL used to request data with.
192194

@@ -203,7 +205,7 @@ Add some initial state to our application so that we can check this.state.movies
203205
```javascript
204206
getInitialState: function() {
205207
return {
206-
movies: null
208+
movies: null,
207209
};
208210
},
209211
```
@@ -272,6 +274,197 @@ Now modify the render function to render a loading view if we don't have any mov
272274

273275
Now press cmd+R and you should see "Loading movies..." until the response comes back, then it will render the first movie it fetched from Rotten Tomatoes.
274276

277+
Screenshot:
278+
279+
<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialSingleFetched.png" alt="screenshot" width="320px" />
280+
275281
## ListView
276282

277283
Let’s now modify this application to render all of this data in a ListView, rather than just the first movie.
284+
285+
Why is a ListView better than just rendering all of these elements or putting them in a ScrollView? Despite React being fast, rendering a possibly infinite list of elements could be slow. ListView schedules rendering of views so that you only display the ones on screen and those already rendered but off screen are removed from the hierarchy.
286+
287+
First thing's first, add the ListView require to the top of the file.
288+
289+
```javascript
290+
var {
291+
AppRegistry,
292+
Image,
293+
ListView,
294+
StyleSheet,
295+
Text,
296+
View,
297+
} = React;
298+
```
299+
300+
Now modify the render funtion so that once we have our data it renders a ListView of movies instead of a single movie.
301+
302+
```javascript
303+
render: function() {
304+
if (!this.state.loaded) {
305+
return this.renderLoadingView();
306+
}
307+
308+
return (
309+
<ListView
310+
dataSource={this.state.dataSource}
311+
renderRow={this.renderMovie}
312+
/>
313+
);
314+
},
315+
```
316+
317+
What is this dataSource thing and why do we use it? This way we can very cheaply know which rows have changed between updates.
318+
319+
You'll notice we added dataSource from this.state. The next step is to add an empty dataSource to getInitialState. Also, now that we're storing the data in dataSource, we should change this.state.movies to be this.state.loaded (boolean) so we aren't storing the data twice.
320+
321+
```javascript
322+
getInitialState: function() {
323+
return {
324+
dataSource: new ListView.DataSource({
325+
rowHasChanged: (row1, row2) => row1 !== row2,
326+
}),
327+
loaded: false,
328+
};
329+
},
330+
```
331+
332+
And here's the modified this.setState in the response handler in fetchData:
333+
334+
```javascript
335+
fetchData: function() {
336+
fetch(REQUEST_URL)
337+
.then((response) => response.json())
338+
.then((responseData) => {
339+
this.setState({
340+
dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
341+
loaded: true,
342+
});
343+
})
344+
.done();
345+
},
346+
```
347+
348+
Screenshot:
349+
350+
<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialFinal.png" alt="screenshot" width="320px" />
351+
352+
353+
### Final source code
354+
355+
```javascript
356+
/**
357+
* Sample React Native App
358+
* https://github.com/facebook/react-native
359+
*/
360+
'use strict';
361+
362+
var React = require('react-native');
363+
var {
364+
AppRegistry,
365+
Image,
366+
ListView,
367+
StyleSheet,
368+
Text,
369+
View,
370+
} = React;
371+
372+
var API_KEY = '7waqfqbprs7pajbz28mqf6vz';
373+
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json';
374+
var PAGE_SIZE = 25;
375+
var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE;
376+
var REQUEST_URL = API_URL + PARAMS;
377+
378+
var SampleApp = React.createClass({
379+
getInitialState: function() {
380+
return {
381+
dataSource: new ListView.DataSource({
382+
rowHasChanged: (row1, row2) => row1 !== row2,
383+
}),
384+
loaded: false,
385+
};
386+
},
387+
388+
componentDidMount: function() {
389+
this.fetchData();
390+
},
391+
392+
fetchData: function() {
393+
fetch(REQUEST_URL)
394+
.then((response) => response.json())
395+
.then((responseData) => {
396+
this.setState({
397+
dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
398+
loaded: true,
399+
});
400+
})
401+
.done();
402+
},
403+
404+
render: function() {
405+
if (!this.state.loaded) {
406+
return this.renderLoadingView();
407+
}
408+
409+
return (
410+
<ListView
411+
dataSource={this.state.dataSource}
412+
renderRow={this.renderMovie}
413+
/>
414+
);
415+
},
416+
417+
renderLoadingView: function() {
418+
return (
419+
<View style={styles.container}>
420+
<Text>
421+
Loading movies...
422+
</Text>
423+
</View>
424+
);
425+
},
426+
427+
renderMovie: function(movie) {
428+
return (
429+
<View style={styles.container}>
430+
<Image
431+
source={{uri: movie.posters.thumbnail}}
432+
style={styles.thumbnail}
433+
/>
434+
<View style={styles.rightContainer}>
435+
<Text style={styles.title}>{movie.title}</Text>
436+
<Text style={styles.year}>{movie.year}</Text>
437+
</View>
438+
</View>
439+
);
440+
},
441+
});
442+
443+
var styles = StyleSheet.create({
444+
container: {
445+
flex: 1,
446+
flexDirection: 'row',
447+
justifyContent: 'center',
448+
alignItems: 'center',
449+
backgroundColor: '#F5FCFF',
450+
},
451+
rightContainer: {
452+
flex: 1,
453+
},
454+
title: {
455+
fontSize: 20,
456+
marginBottom: 8,
457+
textAlign: 'center',
458+
},
459+
year: {
460+
textAlign: 'center',
461+
},
462+
thumbnail: {
463+
width: 53,
464+
height: 81,
465+
},
466+
});
467+
468+
AppRegistry.registerComponent('SampleApp', () => SampleApp);
469+
```
470+

docs/images/TutorialFinal.png

354 KB
Loading

docs/images/TutorialMock.png

58.7 KB
Loading

docs/images/TutorialSingleFetched.png

61.1 KB
Loading

docs/images/TutorialStyledMock.png

58.8 KB
Loading

0 commit comments

Comments
 (0)