Doesn't display information when uploading a file - react native - react-native

good day, I have a button that loads a file from my cell phone and it works, but I need to show the information of the file that I select, such as the name, size, etc. and console.log('res : ' + JSON.stringify(res)); it shows me the information but I have not been able to make it show me the information in the device view it appears undefined it does not show me the information.
import DocumentPicker from 'react-native-document-picker';
const App = () => {
const [singleFile, setSingleFile] = useState('');
const selectOneFile = async () => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res.uri);
console.log('Type : ' + res.type);
console.log('File Name : ' + res.name);
console.log('File Size : ' + res.size);
setSingleFile(res);
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
return (
<TouchableOpacity
activeOpacity={0.5}
style={styles.buttonStyle}
onPress={selectOneFile}>
<Text style={{marginRight: 10, fontSize: 19}}>
Click here to pick one file
</Text>
<Image
source={{
uri: 'https://img.icons8.com/offices/40/000000/attach.png',
}}
style={styles.imageIconStyle}
/>
</TouchableOpacity>
<Text style={styles.textStyle}>
File Name: {singleFile.name ? singleFile.name : ''}
{'\n'}
Type: {singleFile.type ? singleFile.type : ''}
{'\n'}
File Size: {singleFile.size ? singleFile.size : ''}
{'\n'}
URI: {singleFile.uri ? singleFile.uri : ''}
{'\n'}
</Text>
)
console.log

Try this :
import DocumentPicker from 'react-native-document-picker';
const App = () => {
const [singleFile, setSingleFile] = useState({});
React.useEffect(()=>{},[singleFile])
const selectOneFile = async () => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res.uri);
console.log('Type : ' + res.type);
console.log('File Name : ' + res.name);
console.log('File Size : ' + res.size);
setSingleFile(res);
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
return (
<TouchableOpacity
activeOpacity={0.5}
style={styles.buttonStyle}
onPress={selectOneFile}>
<Text style={{marginRight: 10, fontSize: 19}}>
Click here to pick one file
</Text>
<Image
source={{
uri: 'https://img.icons8.com/offices/40/000000/attach.png',
}}
style={styles.imageIconStyle}
/>
</TouchableOpacity>
<Text style={styles.textStyle}>
File Name: {singleFile.name ? singleFile.name : ''}
{'\n'}
Type: {singleFile.type ? singleFile.type : ''}
{'\n'}
File Size: {singleFile.size ? singleFile.size : ''}
{'\n'}
URI: {singleFile.uri ? singleFile.uri : ''}
{'\n'}
</Text>
)

The res is containing an array of objects, that is why you're getting undefined from the console.
If you're selecting just one file and want to show the data, you can try the below
const selectOneFile = async () => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res[0].uri);
setSingleFile(res[0]);
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
If you're selecting multiple files, you can use map or Flatlist to show them.

I was able to solve it, it was just changing res for [res]
const [res] = await DocumentPicker.pick({
import DocumentPicker from 'react-native-document-picker';
const App = () => {
const [singleFile, setSingleFile] = useState('');
const selectOneFile = async () => {
try {
const [res] = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res.uri);
console.log('Type : ' + res.type);
console.log('File Name : ' + res.name);
console.log('File Size : ' + res.size);
setSingleFile(res);
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
return (
<TouchableOpacity
activeOpacity={0.5}
style={styles.buttonStyle}
onPress={selectOneFile}>
<Text style={{marginRight: 10, fontSize: 19}}>
Click here to pick one file
</Text>
<Image
source={{
uri: 'https://img.icons8.com/offices/40/000000/attach.png',
}}
style={styles.imageIconStyle}
/>
</TouchableOpacity>
<Text style={styles.textStyle}>
File Name: {singleFile.name ? singleFile.name : ''}
{'\n'}
Type: {singleFile.type ? singleFile.type : ''}
{'\n'}
File Size: {singleFile.size ? singleFile.size : ''}
{'\n'}
URI: {singleFile.uri ? singleFile.uri : ''}
{'\n'}
</Text>
)

Related

React Native: #react-native-voice/voice not working, not showing any response or results

Does anyone know what could be the issue?
Previously, I was using #react-native-community/voice and it was working. But as I continue developing the application and come back to test the function, it is not working anymore. When I click on the button which initiates Voice.Start(), nothing happened. I thought it could be because it is obsolete. So I changed to #react-native-voice/voice but it is still not working. I tried reinstalling node-module, cleaning the gradle ./gradlew clean but it still doesn't work.
Below is the code I used which was working, but now it isn't. I got this code from the example shown in the #react-native-community/voice example code:
import Voice, {
SpeechRecognizedEvent,
SpeechResultsEvent,
SpeechErrorEvent,}
from '#react-native-voice/voice';
class VoiceTest extends Component{
constructor(props) {
super(props);
this.state = {
pitch: '',
error: '',
end: '',
started: '',
results: [],
partialResults: [],
recognized: '',
}
Voice.onSpeechStart = this.onSpeechStart;
Voice.onSpeechEnd = this.onSpeechEnd;
Voice.onSpeechError = this.onSpeechError;
Voice.onSpeechResults = this.onSpeechResults;
Voice.onSpeechPartialResults = this.onSpeechPartialResults;
Voice.onSpeechVolumeChanged = this.onSpeechVolumeChanged;
}
componentWillUnmount() {
Voice.destroy().then(Voice.removeAllListeners);
}
onSpeechStart = (e) => {
console.log('onSpeechStart: ', e);
};
onSpeechEnd = (e) => {
console.log('onSpeechEnd: ', e);
};
onSpeechError = (e) => {
console.log('onSpeechError: ', e);
};
onSpeechResults = (e) => {
console.log('onSpeechResults: ', e);
};
onSpeechPartialResults = (e) => {
console.log('onSpeechPartialResults: ', e);
};
onSpeechVolumeChanged = (e) => {
console.log('onSpeechVolumeChanged: ', e);
};
_startRecognizing = async () => {
this.setState({
recognized: '',
pitch: '',
error: '',
started: '',
results: [],
partialResults: [],
end: '',
});
try {
await Voice.start('en-US');
};
_stopRecognizing = async () => {
await Voice.stop();
};
_cancelRecognizing = async () =>{
await Voice.cancel();
};
_destroyRecognizer = async () => {
await Voice.destroy();
this.setState({
recognized: '',
pitch: '',
error: '',
started: '',
results: [],
partialResults: [],
end: '',
});
};
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native Voice!</Text>
<Text style={styles.instructions}>
Press the button and start speaking.
</Text>
<Text style={styles.stat}>{`Started: ${this.state.started}`}</Text>
<Text style={styles.stat}>{`Recognized: ${
this.state.recognized
}`}</Text>
<Text style={styles.stat}>{`Pitch: ${this.state.pitch}`}</Text>
<Text style={styles.stat}>{`Error: ${this.state.error}`}</Text>
<Text style={styles.stat}>Results</Text>
{this.state.results.map((result, index) => {
return (
<Text key={`result-${index}`} style={styles.stat}>
{result}
</Text>
);
})}
<Text style={styles.stat}>Partial Results</Text>
{this.state.partialResults.map((result, index) => {
return (
<Text key={`partial-result-${index}`} style={styles.stat}>
{result}
</Text>
);
})}
<Text style={styles.stat}>{`End: ${this.state.end}`}</Text>
<TouchableHighlight onPress={this._startRecognizing}>
<Text style={{fontSize:36, backgroundColor: '#ccc'}}>Button</Text>
{/* <Image style={styles.button} source={require('./button.png')} /> */}
</TouchableHighlight>
<TouchableHighlight onPress={this._stopRecognizing}>
<Text style={styles.action}>Stop Recognizing</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this._cancelRecognizing}>
<Text style={styles.action}>Cancel</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this._destroyRecognizer}>
<Text style={styles.action}>Destroy</Text>
</TouchableHighlight>
</View>
);
}
}
Versions Used:
"react-native": "0.63.4",
buildToolsVersion = "29.0.2"
minSdkVersion = 19
compileSdkVersion = 29
targetSdkVersion = 31
kotlinVersion = "1.6.0"

How to show the image which is picked with react native image picker?

Problem:
I have created an image and video picker with react-native-image-picker. This is how my code looks like.
import React, {useState, createRef} from 'react';
import {
View,
TouchableOpacity,
Image,
TouchableWithoutFeedback,
} from 'react-native';
import AppText from '_components/appText';
import Icon from 'react-native-vector-icons/AntDesign';
import {strings} from '_translations/i18n';
import styles from './newpatientassetmentstyle';
import PlayerControls from '_components/playerControls';
import Video from 'react-native-video';
import ImagePicker from 'react-native-image-picker';
const showControls = (state, setState) => {
state.showControls
? setState({...state, showControls: false})
: setState({...state, showControls: true});
};
const handlePlayPause = (state, setState) => {
if (state.play) {
setState({...state, play: false, showControls: true});
return;
}
setState({...state, play: true});
setTimeout(() => setState((s) => ({...s, showControls: false})), 2000);
};
function onLoadEnd(data, state, setState) {
setState({
...state,
duration: data.duration,
currentTime: data.currentTime,
});
}
function onProgress(data, state, setState) {
setState({
...state,
currentTime: data.currentTime,
});
}
const onEnd = (state, setState, player) => {
setState({
...state,
showControls: false,
play: false,
currentTime: 0,
duration: 0,
});
player.current.seek(0);
};
const openPicker = async (type, setFileObject) => {
let options;
if (type === 4) {
options = {
title: 'Upload Image',
quality: 1,
mediaType: 'photo',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
} else if (type === 5) {
options = {
title: 'Upload Video',
videoQuality: 'high',
mediaType: 'video',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
}
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
setFileObject(response);
}
});
};
const DocumentUpload = (props) => {
const {type} = props;
const [fileObject, setFileObject] = useState(null);
const [state, setState] = useState({
fullscreen: false,
play: false,
currentTime: 0,
duration: 0,
showControls: true,
});
const player = createRef();
return (
<View>
{type === 5 && (
<View style={styles.videoContainer}>
<View style={styles.videoInnerContainer}>
<TouchableWithoutFeedback
onPress={() => showControls(state, setState)}>
<View style={{flex: 1}}>
<Video
source={{
uri: fileObject.uri,
}}
controls={false}
style={styles.backgroundVideo}
ref={player}
resizeMode={'contain'}
paused={!state.play}
onEnd={() => onEnd(state, setState, player)}
onLoad={(data) => onLoadEnd(data, state, setState)}
onProgress={(data) => onProgress(data, state, setState)}
/>
{state.showControls && (
<View style={styles.controlsOverlay}>
<PlayerControls
play={state.play}
playVideo={handlePlayPause}
state={state}
setState={setState}
pauseVideo={handlePlayPause}
/>
</View>
)}
</View>
</TouchableWithoutFeedback>
</View>
</View>
)}
{fileObject
? console.log(`data:${fileObject.type},${fileObject.data}`, 'fileOb')
: null}
{type === 4 && fileObject && (
<View>
<Image
source={{uri: 'data:' + fileObject.type + ',' + fileObject.data}}
/>
</View>
)}
{!fileObject ? (
<>
<TouchableOpacity onPress={() => openPicker(type, setFileObject)}>
<Image
source={require('_assets/img/cmerap.png')}
resizeMode="center"
style={styles.camPImage}
/>
</TouchableOpacity>
<AppText styles={styles.camPText}>
{strings('assetsment.capture')}
</AppText>
</>
) : (
<View style={styles.videoBottomText}>
<TouchableOpacity onPress={() => openPicker(type, setFileObject)}>
<View style={styles.updateAgainContainer}>
<Icon name="reload1" style={styles.reloadIcon} />
<AppText styles={styles.reloadText}>
{strings('assetsment.reload')}
</AppText>
</View>
</TouchableOpacity>
</View>
)}
</View>
);
};
export default DocumentUpload;
But when I try to show the picked image in the view but it is showing nothing in there. I tried a lot to find out what is wrong with this but I was unable to do so. Can someone help me to find out a solution to this problem? Thank you very much.
Once you have the image selected you'll have a response object, in which you'll have the uri for the image chosen (you can console.log the response object to make sure what the key for the uri is). Once you have this object with the response, use its uri to set a state and make sure you use that state in your image tag, like this: source={{ uri: imageUriFromState }}

Speech to Text in React Native with react-native-community/voice

I want to convert voice to text and get the texts as a result with the help of voice recognition.
I'm using react-native-community/voice (Example)
After building the project and install apk on my phone and press record button, I get the following error :
Error: {"message":"5/Client side error"}
NOTE: I added the following permission in AndroidManifest:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
this is my code ():
import React, { Component, useState, useEffect } from 'react';
import { StyleSheet, Text, View, Image, TouchableHighlight } from 'react-native';
import Voice from '#react-native-community/voice';
const App = (props) => {
const [voiceState, setVoiceState] = useState({
recognized: '',
pitch: '',
error: '',
end: '',
started: '',
results: [],
partialResults: [],
})
useEffect(() => {
Voice.onSpeechStart = onSpeechStart;
Voice.onSpeechRecognized = onSpeechRecognized;
Voice.onSpeechEnd = onSpeechEnd;
Voice.onSpeechError = onSpeechError;
Voice.onSpeechResults = onSpeechResults;
Voice.onSpeechPartialResults = onSpeechPartialResults;
Voice.onSpeechVolumeChanged = onSpeechVolumeChanged;
Voice.destroy().then(Voice.removeAllListeners);
}, [])
const onSpeechStart = (e) => {
console.log('onSpeechStart: ', e);
setVoiceState({ ...voiceState, started: '√', })
};
const onSpeechRecognized = (e) => {
console.log('onSpeechRecognized: ', e);
setVoiceState({
...voiceState, recognized: '√',
})
};
const onSpeechEnd = (e) => {
console.log('onSpeechEnd: ', e);
setVoiceState({
...voiceState, end: '√',
})
};
const onSpeechError = (e) => {
console.log('onSpeechError: ', e);
setVoiceState({
...voiceState, error: JSON.stringify(e.error)
})
};
const onSpeechResults = (e) => {
console.log('onSpeechResults: ', e);
setVoiceState({
...voiceState, results: e.value,
})
};
const onSpeechPartialResults = (e) => {
console.log('onSpeechPartialResults: ', e);
setVoiceState({
...voiceState, partialResults: e.value,
})
};
const onSpeechVolumeChanged = (e) => {
console.log('onSpeechVolumeChanged: ', e);
setVoiceState({
...voiceState, pitch: e.value,
})
};
const _startRecognizing = async () => {
setVoiceState({
...voiceState,
recognized: '',
pitch: '',
error: '',
started: '',
results: [],
partialResults: [],
end: '',
})
try {
await Voice.start('en-US');
} catch (e) {
console.error(e);
}
};
const _stopRecognizing = async () => {
try {
await Voice.stop();
} catch (e) {
console.error(e);
}
};
const _cancelRecognizing = async () => {
try {
await Voice.cancel();
} catch (e) {
console.error(e);
}
};
const _destroyRecognizer = async () => {
try {
await Voice.destroy();
} catch (e) {
console.error(e);
}
setVoiceState({
...voiceState,
recognized: '',
pitch: '',
error: '',
started: '',
results: [],
partialResults: [],
end: '',
})
};
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native Voice!</Text>
<Text style={styles.instructions}>
Press the button and start speaking.
</Text>
<Text style={styles.stat}>{`Started: ${voiceState.started}`}</Text>
<Text style={styles.stat}>{`Recognized: ${
voiceState.recognized
}`}</Text>
<Text style={styles.stat}>{`Pitch: ${voiceState.pitch}`}</Text>
<Text style={styles.stat}>{`Error: ${voiceState.error}`}</Text>
<Text style={styles.stat}>Results</Text>
{voiceState.results.map((result, index) => {
return (
<Text key={`result-${index}`} style={styles.stat}>
{result}
</Text>
);
})}
<Text style={styles.stat}>Partial Results</Text>
{voiceState.partialResults.map((result, index) => {
return (
<Text key={`partial-result-${index}`} style={styles.stat}>
{result}
</Text>
);
})}
<Text style={styles.stat}>{`End: ${voiceState.end}`}</Text>
<TouchableHighlight onPress={_startRecognizing}>
<Image style={styles.button} source={require('../assets/voice-recording.png')} />
</TouchableHighlight>
<TouchableHighlight onPress={_stopRecognizing}>
<Text style={styles.action}>Stop Recognizing</Text>
</TouchableHighlight>
<TouchableHighlight onPress={_cancelRecognizing}>
<Text style={styles.action}>Cancel</Text>
</TouchableHighlight>
<TouchableHighlight onPress={_destroyRecognizer}>
<Text style={styles.action}>Destroy</Text>
</TouchableHighlight>
</View>
);
}
I've seen this happen on an android emulator before, however it didn't happen on a real device. It could be that the emulator/device you're using doesn't have speech recognition support.
Before starting the listener, you should use the isAvailable method from the library to make sure the device is able to handle speech recognition.

How to get ref in flat list item onpress?

I am trying to capture screen with react-native-view-shot. On press this.refs.viewShot.capture showing undefined.
Here is my code
Flat list code:
<FlatList
ref={(list) => this.myFlatList = list}
data={this.state.newsListArray}
keyExtractor={this._keyExtractor}
renderItem={this.renderRowItem}
/>
render on press link:
<TouchableOpacity onPress={ () => {
Platform.OS === 'ios' ?
this._captureScreenIos('5c63f7307518134a2aa288ce') :
this._captureScreenAndroid('5c63f7307518134a2aa288ce')
}}>
<View style={{flexDirection:'row'}}>
<Icon name="share-alt" size={16} color="#ffb6cf" />
<Text style={{paddingLeft:6,fontSize:12,fontWeight:'500'}}>Share News</Text>
</View>
</TouchableOpacity>
And that's the function:
_captureScreenIos = (refId) => {
console.log("Clicked for IOS");
this.changeLoaderStatus();
var thisFun = this;
var viewShotRef = 'viewShot-5c63f7307518134a2aa288ce';
this.myFlatList.viewShot.capture({width: 2048 / PixelRatio.get(), height: 2048 / PixelRatio.get()}).then(res => {
RNFetchBlob.fs.readFile(res, 'base64').then((base64data) => {
console.log("base64data",base64data)
let base64Image = `data:image/jpeg;base64,${base64data}`;
const shareOptions = {
title: "My Beauty Squad",
//message: "Download my beauty squad with below link."+ "\n" + "https://itunes.apple.com/uk/app/my-beauty-squad/id1454212046?mt=8" ,
url: base64Image,
subject: "Share news feed"
};
Share.open(shareOptions);
thisFun.changeLoaderStatus();
})
}).catch(error => {
console.log(error, 'this is error');
this.changeLoaderStatus();
})
}
Please let me know if anyone having a solution for the same.
**This is my app screen **
It's blur when we have long list items.
Try this:
import { captureRef } from react-native-view-shot
constructor(props) {
super(props);
this.refs = {};
}
renderItem = ({item, index}) => (
<TouchableOpacity
onPress={ () => {
captureRef(this.refs[`${index}`], options).then(.....)
}
>
<View
style={{flexDirection:'row'}}
ref={shot => this.refs[`${index}`] = shot}
>
...........
</View>
</TouchableOpacity>
)
React Native View Shot
I hope it help you.
That is a good amount of code. Try https://reactnativecode.com/take-screenshot-of-app-programmatically/
setting the state and try passing in the object you are referencing.
export default class App extends Component {
constructor(){
super();
this.state={
imageURI : 'https://reactnativecode.com/wp-content/uploads/2018/02/motorcycle.jpg'
}
}
captureScreenFunction=()=>{
captureScreen({
format: "jpg",
quality: 0.8
})
.then(
uri => this.setState({ imageURI : uri }),
error => console.error("Oops, Something Went Wrong", error)
);
}
Here is answer:
constructor(props) {
this.screenshot = {};
}
This is my function:
_captureScreenIos(itemId) {
this.changeLoaderStatus();
var thisFun = this;
var viewShotRef = itemId;
captureRef(this.screenshot[itemId],{format: 'jpg',quality: 0.8}).then(res => {
RNFetchBlob.fs.readFile(res, 'base64').then((base64data) => {
console.log("base64data",base64data)
let base64Image = `data:image/jpeg;base64,${base64data}`;
const shareOptions = {
title: "My Beauty Squad",
//message: "Download my beauty squad with below link."+ "\n" + "https://itunes.apple.com/uk/app/my-beauty-squad/id1454212046?mt=8" ,
url: base64Image,
subject: "Share news feed"
};
Share.open(shareOptions);
thisFun.changeLoaderStatus();
})
}).catch(error => {
console.log(error, 'this is error');
this.changeLoaderStatus();
})
}
This is the view:
<View collapsable={false} ref={(shot) => { this.screenshot[itemId] = shot; }} >
//some content here
<TouchableOpacity onPress={ () => {
Platform.OS === 'ios' ?
this._captureScreenIos(itemData.item._id) :
this._captureScreenAndroid(itemData.item._id)
}}>
<View style={{flexDirection:'row'}}>
<Icon name="share-alt" size={16} color="#ffb6cf" />
<Text style={{paddingLeft:6,fontSize:12,fontWeight:'500'}}>Share News</Text>
</View>
</TouchableOpacity>
</View>

How to upload a photo to a backend server along with form data using API?

Here below is my code, I am trying to capture an image and filling the other input field. Once I click on create button, I am calling an api to upload it to the backend server. But how Do I send the file details to backend? I have the working api in postman. And some of the fields I have not included some of the input field code here because the code will be large here.
API takes the following fields in postman
import React, {Component} from 'react';
import {
StyleSheet,
Button,
TextInput,
Text,
TouchableOpacity,
View,
Picker,
Image,
} from 'react-native';
import ImagePicker from 'react-native-image-picker';
export default class CreateStudent extends React.Component {
constructor(props){
super(props);
this.state = {
studentName: '',
email: '',
newPassword: '',
fileShow: '',
faceDetails: '',
school: 1,
}
}
handleEmail = (text) => {
this.setState({ email: text })
}
handlePassword = (text) => {
this.setState({ newPassword: text })
}
handleName = (text) => {
this.setState({ studentName: text })
}
selectImage = () => {
const options = {
quality: 1.0,
maxWidth: 75,
maxHeight: 75
}
ImagePicker.launchCamera(options,(responce)=>{
const fileDetails ={
uri : responce.uri,
name :responce.fileName,
method: 'POST',
width : 50,
height : 50,
path : responce.path,
type : responce.type,
}
this.setState({
fileShow: responce.uri,
faceDetails: fileDetails
})
console.log(this.state.fileShow);
console.log(fileDetails);
})
}
async onCreateStudentPressed() {
try {
let response = await fetch('http://10.0.2.2:5000/api/students/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
file: this.state.fileDetails,
email: this.state.email,
password: this.state.newPassword,
phone_number: this.state.phoneNumber,
class: this.state.class,
section: this.state.section,
school: this.state.school,
name: this.state.studentName
})
});
let res = await response.text();
if (response.status >= 200 && response.status < 300) {
//Handle success
let accessToken = res;
console.log(accessToken);
//On success we will store the access_token in the AsyncStorage
//this.storeToken(accessToken);
} else {
//Handle error
let error = res;
throw error;
}
} catch(error) {
this.setState({error: error});
console.log("error " + error);
this.setState({
passwordUpdated: false
})
}
}
render() {
return (
<View>
<View style={styles.formContainer}>
<Text style ={styles.pageTitle} >Create Student</Text>
<View style={styles.Camera}>
<TouchableOpacity onPress={this.selectImage}>
<Text>Take Picture</Text>
</TouchableOpacity>
</View>
{
this.state.fileShow !== '' ?
<View style={styles.showBlack}>
<View style={styles.placeholder}>
<Image key={1} source={{uri: this.state.fileShow}} style={styles.previewImage} />
</View>
</View>
:
null
}
<TextInput
placeholder='Enter Student Name'
placeholderTextColor='#808080'
style ={styles.textInput}
underlineColorAndroid={'transparent'}
onChangeText = {this.handleName}
/>
<TextInput
placeholder='Enter Student Email'
placeholderTextColor='#808080'
style ={styles.textInput}
underlineColorAndroid={'transparent'}
onChangeText = {this.handleEmail}
/>
<TextInput
placeholder='Enter Password'
placeholderTextColor='#808080'
secureTextEntry={true}
style ={styles.textInput}
underlineColorAndroid={'transparent'}
onChangeText = {this.handlePassword}
/>
<Button
onPress={this.onCreateStudentPressed.bind(this)}
style ={styles.loginBtn}
title="Create"
/>
</View>
</View>
);
}
}
There are various ways you can achieve this. I am going to highlight the easiest way for you to do this. I assume you have a storage service such as Amazon S3 where you store the photo. The easiest way is for you to first upload the image to your S3, the response body will include the url to the uploaded photo. Then you can take that url together with your form values and pass them to your backend.
//Example.js
import React, { Component } from 'react';
import {
//Whatever RN Components you need
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
TextInput,
ActivityIndicator,
ScrollView,
Picker,
Linking,
Image,
} from 'react-native';
import axios from 'axios';
import { RNS3 } from 'react-native-aws3';
import ImagePicker from 'react-native-image-picker';
export default class RegisterScreen extends Component {
state = {
email: '',
password: '',
confirmedPassword: '',
firstName: '',
lastName: '',
avatar: '',
avatarUri: '',
avatarName: '',
avatarType: '',
loading: false,
errorMessage: '',
uploadMessage: ''
}
onRegisterPress = () => {
this.setState({
errorMessage: '',
registerLoading: true,
uploadMessage: 'This may take a while: Uploading your Profile Pic...'
});
const avatarFile = {
uri: this.state.avatarUri,
name: this.state.avatarName,
type: this.state.avatarType
};
const avatarOptions = {
keyPrefix: 'uploads/path/avatar/' + this.state.email + '/' + new Date().getTime(),
bucket: 'your-bucket-s3',
region: 'us-west-2',
accessKey: 'ACCESSKEY',
secretKey: 'SECRETKEY',
successActionStatus: 201
};
RNS3.put(avatarFile, avatarOptions)
.then((response) => {
if (response.status === 201) {
this.setState({ avatar: response.body.postResponse.location });
} else {//handle error}
})
.then(() => {
this.setState({
uploadMessage: 'Creating your profile'
});
const url = 'someremoteurl.com';
const payload = {
email: this.state.email,
password: this.state.password,
password_confirmation: this.state.confirmedPassword,
first_name: this.state.firstName,
last_name: this.state.lastName,
avatar: this.state.avatar,
};
axios.post(url, payload)
.then((r) => {
this.setState({
uploadMessage: '',
loading: false
});
if (r.status === 200) {
//handle success
}
})
.catch(() => {
// handle form submission error
this.setState({
uploadMessage: '',
loading: false,
error: true
});
});
});
}
openMediaLibrary() {
const options = {
title: 'Select Photo',
storageOptions: {
skipBackup: true,
path: 'images'
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('Cancelled selection of image');
} else if (response.error) {
console.log('Image Picker error', response.error)
} else {
this.setState({
avatarUri: response.uri,
avatarName: response.fileName,
avatarType: response.type
});
}
});
}
render() {
return (
<ScrollView style={{ margin: 15 }}>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Email</Text>
<TextInput
placeholder='john#yahoo.com'
underlineColorAndroid='transparent'
onChangeText={(email) => this.setState({ email })}
value={this.state.email}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Password (minimum of 8 letters)</Text>
<TextInput
placeholder='password'
underlineColorAndroid='transparent'
onChangeText={(password) => this.setState({ password })}
value={this.state.password}
secureTextEntry
autoCorrect={false}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Password Confirmation</Text>
<TextInput
placeholder='retype your password'
underlineColorAndroid='transparent'
onChangeText={(confirmedPassword) => this.setState({ confirmedPassword })}
value={this.state.confirmedPassword}
secureTextEntry
autoCorrect={false}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> First Name</Text>
<TextInput
placeholder='First Name'
underlineColorAndroid='transparent'
onChangeText={(firstName) => this.setState({ firstName })}
value={this.state.firstName}
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}>Last Name</Text>
<TextInput
placeholder='Last Name'
underlineColorAndroid='transparent'
onChangeText={(lastName) => this.setState({ lastName })}
value={this.state.lastName}
/>
</View>
<View>
<View style={{ padding: 10 }}>
{
this.state.avatarUri.length > 0 ?
<Image
source={{ uri: this.state.avatarUri }}
style={{ width: 140, height: 140 }}
/>
: null
}
</View>
<Button
small
backgroundColor='#13CE66'
title={(this.state.avatarUri.length === 0) ?
'Choose Profile Picture' : 'Change Profile Picture'}
onPress={() => this.openMediaLibrary()}
/>
</View>
<Button
large
backgroundColor='#13CE66'
title='Submit'
onPress={() => this.onRegisterPress() }
/>
</ScrollView>
)
}
}
So when you attempt to register this user, the image is first uploaded and the retrieved url is stored in state to be used as part of form params for avatar.
This is easy, the downside is having to wait for upload response before actually having to send your form params
EDIT
If you are not using a 3rd party storage service or if you would rather send the file to your own servers then use FormData():
//OnRegisterPress function should look like this:
onRegisterPress = () => {
let form = new FormData();
form.append('avatar', {
//from openMedia Function, image selected with image-picker
uri: this.state.avatarUri,
name: this.state.avatarName,
type: this.state.avatarType
});
// append your other params such as email, password, name
form.append('email', this.state.email)
form.append('password', this.state.password)
// when you are done appending, use fetch to send the form data as axios seems to be having a bit of issues doing this.
fetch('http://yourapiendpoint', {
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
method: 'POST',
body: form
});
}