1717
1818var React = require ( 'react-native' ) ;
1919var {
20+ AlertIOS,
21+ CameraRoll,
22+ Image,
23+ LinkingIOS,
24+ PixelRatio,
2025 ProgressViewIOS,
2126 StyleSheet,
22- View,
2327 Text,
28+ TextInput,
2429 TouchableHighlight,
30+ View,
2531} = React ;
2632
2733class Downloader extends React . Component {
@@ -109,6 +115,177 @@ class Downloader extends React.Component {
109115 }
110116}
111117
118+ var PAGE_SIZE = 20 ;
119+
120+ class FormUploader extends React . Component {
121+
122+ constructor ( props ) {
123+ super ( props ) ;
124+ this . state = {
125+ isUploading : false ,
126+ randomPhoto : null ,
127+ textParams : [ ] ,
128+ } ;
129+ this . _isMounted = true ;
130+ this . _fetchRandomPhoto = this . _fetchRandomPhoto . bind ( this ) ;
131+ this . _addTextParam = this . _addTextParam . bind ( this ) ;
132+ this . _upload = this . _upload . bind ( this ) ;
133+
134+ this . _fetchRandomPhoto ( ) ;
135+ }
136+
137+ _fetchRandomPhoto ( ) {
138+ CameraRoll . getPhotos (
139+ { first : PAGE_SIZE } ,
140+ ( data ) => {
141+ console . log ( 'isMounted' , this . _isMounted ) ;
142+ if ( ! this . _isMounted ) {
143+ return ;
144+ }
145+ var edges = data . edges ;
146+ var edge = edges [ Math . floor ( Math . random ( ) * edges . length ) ] ;
147+ var randomPhoto = edge && edge . node && edge . node . image ;
148+ if ( randomPhoto ) {
149+ this . setState ( { randomPhoto} ) ;
150+ }
151+ } ,
152+ ( error ) => undefined
153+ ) ;
154+ }
155+
156+ _addTextParam ( ) {
157+ var textParams = this . state . textParams ;
158+ textParams . push ( { name : '' , value : '' } ) ;
159+ this . setState ( { textParams} ) ;
160+ }
161+
162+ componentWillUnmount ( ) {
163+ this . _isMounted = false ;
164+ }
165+
166+ _onTextParamNameChange ( index , text ) {
167+ var textParams = this . state . textParams ;
168+ textParams [ index ] . name = text ;
169+ this . setState ( { textParams} ) ;
170+ }
171+
172+ _onTextParamValueChange ( index , text ) {
173+ var textParams = this . state . textParams ;
174+ textParams [ index ] . value = text ;
175+ this . setState ( { textParams} ) ;
176+ }
177+
178+ _upload ( ) {
179+ var xhr = new XMLHttpRequest ( ) ;
180+ xhr . open ( 'POST' , 'http://posttestserver.com/post.php' ) ;
181+ xhr . onload = ( ) => {
182+ this . setState ( { isUploading : false } ) ;
183+ if ( xhr . status !== 200 ) {
184+ AlertIOS . alert (
185+ 'Upload failed' ,
186+ 'Expected HTTP 200 OK response, got ' + xhr . status
187+ ) ;
188+ return ;
189+ }
190+ if ( ! xhr . responseText ) {
191+ AlertIOS . alert (
192+ 'Upload failed' ,
193+ 'No response payload.'
194+ ) ;
195+ return ;
196+ }
197+ var index = xhr . responseText . indexOf ( 'http://www.posttestserver.com/' ) ;
198+ if ( index === - 1 ) {
199+ AlertIOS . alert (
200+ 'Upload failed' ,
201+ 'Invalid response payload.'
202+ ) ;
203+ return ;
204+ }
205+ var url = xhr . responseText . slice ( index ) . split ( '\n' ) [ 0 ] ;
206+ LinkingIOS . openURL ( url ) ;
207+ } ;
208+ var formdata = new FormData ( ) ;
209+ if ( this . state . randomPhoto ) {
210+ formdata . append ( 'image' , { ...this . state . randomPhoto , name : 'image.jpg' } ) ;
211+ }
212+ this . state . textParams . forEach (
213+ ( param ) => formdata . append ( param . name , param . value )
214+ ) ;
215+ xhr . send ( formdata ) ;
216+ this . setState ( { isUploading : true } ) ;
217+ }
218+
219+ render ( ) {
220+ var image = null ;
221+ if ( this . state . randomPhoto ) {
222+ image = (
223+ < Image
224+ source = { this . state . randomPhoto }
225+ style = { styles . randomPhoto }
226+ />
227+ ) ;
228+ }
229+ var textItems = this . state . textParams . map ( ( item , index ) => (
230+ < View style = { styles . paramRow } >
231+ < TextInput
232+ autoCapitalize = "none"
233+ autoCorrect = { false }
234+ onChangeText = { this . _onTextParamNameChange . bind ( this , index ) }
235+ placeholder = "name..."
236+ style = { styles . textInput }
237+ />
238+ < Text style = { styles . equalSign } > =</ Text >
239+ < TextInput
240+ autoCapitalize = "none"
241+ autoCorrect = { false }
242+ onChangeText = { this . _onTextParamValueChange . bind ( this , index ) }
243+ placeholder = "value..."
244+ style = { styles . textInput }
245+ />
246+ </ View >
247+ ) ) ;
248+ var uploadButtonLabel = this . state . isUploading ? 'Uploading...' : 'Upload' ;
249+ var uploadButton = (
250+ < View style = { styles . uploadButtonBox } >
251+ < Text style = { styles . uploadButtonLabel } > { uploadButtonLabel } </ Text >
252+ </ View >
253+ ) ;
254+ if ( ! this . state . isUploading ) {
255+ uploadButton = (
256+ < TouchableHighlight onPress = { this . _upload } >
257+ { uploadButton }
258+ </ TouchableHighlight >
259+ ) ;
260+ }
261+ return (
262+ < View >
263+ < View style = { [ styles . paramRow , styles . photoRow ] } >
264+ < Text style = { styles . photoLabel } >
265+ Random photo from your library
266+ (< Text style = { styles . textButton } onPress = { this . _fetchRandomPhoto } >
267+ update
268+ </ Text > )
269+ </ Text >
270+ { image }
271+ </ View >
272+ { textItems }
273+ < View >
274+ < Text
275+ style = { [ styles . textButton , styles . addTextParamButton ] }
276+ onPress = { this . _addTextParam } >
277+ Add a text param
278+ </ Text >
279+ </ View >
280+ < View style = { styles . uploadButton } >
281+ { uploadButton }
282+ </ View >
283+ </ View >
284+ ) ;
285+ }
286+ }
287+
288+
112289exports . framework = 'React' ;
113290exports . title = 'XMLHttpRequest' ;
114291exports . description = 'XMLHttpRequest' ;
@@ -117,6 +294,11 @@ exports.examples = [{
117294 render ( ) {
118295 return < Downloader /> ;
119296 }
297+ } , {
298+ title : 'multipart/form-data Upload' ,
299+ render ( ) {
300+ return < FormUploader /> ;
301+ }
120302} ] ;
121303
122304var styles = StyleSheet . create ( {
@@ -126,6 +308,52 @@ var styles = StyleSheet.create({
126308 } ,
127309 button : {
128310 backgroundColor : '#eeeeee' ,
129- padding : 10 ,
311+ padding : 8 ,
312+ } ,
313+ paramRow : {
314+ flexDirection : 'row' ,
315+ paddingVertical : 8 ,
316+ alignItems : 'center' ,
317+ borderBottomWidth : 1 / PixelRatio . get ( ) ,
318+ borderBottomColor : 'grey' ,
319+ } ,
320+ photoLabel : {
321+ flex : 1 ,
322+ } ,
323+ randomPhoto : {
324+ width : 50 ,
325+ height : 50 ,
326+ } ,
327+ textButton : {
328+ color : 'blue' ,
329+ } ,
330+ addTextParamButton : {
331+ marginTop : 8 ,
332+ } ,
333+ textInput : {
334+ flex : 1 ,
335+ borderRadius : 3 ,
336+ borderColor : 'grey' ,
337+ borderWidth : 1 ,
338+ height : 30 ,
339+ paddingLeft : 8 ,
340+ } ,
341+ equalSign : {
342+ paddingHorizontal : 4 ,
343+ } ,
344+ uploadButton : {
345+ marginTop : 16 ,
346+ } ,
347+ uploadButtonBox : {
348+ flex : 1 ,
349+ paddingVertical : 12 ,
350+ alignItems : 'center' ,
351+ backgroundColor : 'blue' ,
352+ borderRadius : 4 ,
353+ } ,
354+ uploadButtonLabel : {
355+ color : 'white' ,
356+ fontSize : 16 ,
357+ fontWeight : '500' ,
130358 } ,
131359} ) ;
0 commit comments