I am trying to set up a session in my react native
I am new to mobile app development. I don't know whether this is the correct approach to set a session
I am coming from react js background so I tried this approach but in the application tab in react native debugger I dont find the session token set can someone explain and help me whether this is a correct approach
axios({
method: 'POST',
url: 'http://127.0.0.1:8000/api/register',
data: Data56,
});
.then(function (response) {
storeData(response.data.token);
alert('sucess');
.catch(error => {
alert(JSON.stringify(error.response, 'catch'));
});
}
first install
npm install react-client-session --save
Then
import { ReactSession } from 'react-client-session';
function Login() {
ReactSession.setStoreType("localStorage");
ReactSession.set("username", "Meon");
return (
<div>
<Switch>
// Routes
</Switch>
</div>
);
}
export default Login;
Then Call your session anywhere as like this
const loggedIn = ReactSession.get("username");
You can use #react-native-async-storage/async-storage library for storing your AUTH_TOKEN. Here is the code with explanation.
When user login your api would return a token that you can store the in the AysncStorage.
const storeData = async (value) => {
try {
await AsyncStorage.setItem('auth_token', value)
} catch (e) {
// saving error
}
}
and with this function you can get your token.
const [auth_token, setAuthToken ] = useState(null);
const getData = async () => {
try {
const value = await AsyncStorage.getItem('auth_token')
if(value !== null) {
setAuthToken(value)
}
} catch(e) {
// error reading value
}
}
Here you can use it like this.
axios
.post('http://10.0.2.2:8000/api/register', Data56)
.then(function (response) {
storeData(réponse.token)
})
.catch(error => {
alert(JSON.stringify(error.response, 'catch'));
});
}
After you set your token , on the start of the application get the token and store it the redux-store. of the token is null redirect user to login else redirect to Home Screen .
on API call use can use that token like this.
var config = {
method: 'post',
url: 'https://my.api.url.com//v1/delete_user_account.php?id=98744',
headers: {
'Authorization': `Bearer ${auth_token}`,
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Here is the code where you can store a token and get that token back.
import AsyncStorage from '#react-native-async-storage/async-storage';
import React from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
const App = () => {
const auth_session_token = 'AwdcE39dsC#43d#2023jlkre2DWjKLD';
const store_token = (async = value => {
AsyncStorage.setItem('token', `${value}`)
.then(() => {
alert('token is stored');
})
.catch(err => {
alert('some Error', JSON.stringify(err));
});
});
const get_auth_token = () => {
AsyncStorage.getItem('token')
.then(token => {
console.log(token);
alert(JSON.stringify(token));
})
.catch(err => {
console.log('Some Eorr');
alert('THere is some error', JSON.stringify(err));
});
};
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<TouchableOpacity
onPress={() => store_token(auth_session_token)}
style={{
width: 200,
height: 50,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#0090FF',
}}>
<Text style={{color: '#fff', fontWeight: 'bold'}}>Store Token</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => get_auth_token()}
style={{
width: 200,
height: 50,
marginTop: 60,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#0090FF',
}}>
<Text style={{color: '#fff', fontWeight: 'bold'}}>Get Token</Text>
</TouchableOpacity>
</View>
);
};
export default App;
While handling tokens it's better to use react-native-keychain. It is more secure than async storage and better for storing sensitive data.
install and import keychain :
npm i react-native-keychain --legacy-peer-deps
import * as Keychain from 'react-native-keychain';
In your case try this approach :
axios({
method: 'POST',
url: 'http://127.0.0.1:8000/api/register',
data: Data56,
});
.then(async function (response) {
storeData(response.data.token);
await Keychain.setGenericPassword(response.data.token);
alert('sucess');
.catch(error => {
alert(JSON.stringify(error.response, 'catch'));
});
}
If your tokens are not strings and you need to store an Object, just stringify them using
JSON.stringify(response.data.token)
and retrieve the token anywhere using :
const token = await Keychain.getGenericPassword();
You can also reset a session easily using :
await Keychain.resetGenericPassword();
Here is simple way using the Async Storage it's similar window.localStorage.
Install React Native Async Storage
npm install #react-native-async-storage/async-storage --save
Now make a api helper name with api.js
import AsyncStorage from '#react-native-async-storage/async-storage'
import axios from 'axios';
export let BASE_URL = 'http://127.0.0.1:8000/api/'
export let GET = async (params)=>{
let token = await AsyncStorage.getItem('#token')
return axios({method:'GET', url:BASE_URL+params,
headers: {
Authorization: token, //here use Bearer token with prefix
}
})
}
export let POST = async (endpoint,params)=>{
let token = await AsyncStorage.getItem('#token')
return axios({
method:'POST',
url:BASE_URL+endpoint,
headers: {
Authorization: token, //here use Bearer token with prefix
},
data:JSON.stringify(params)
})
}
Now store the token into the Async Storage
import {POST} from "./helper/api"
import AsyncStorage from '#react-native-async-storage/async-storage'
POST('register',Data56).then(function (response) {
AsyncStorage.setItem('#token',response.data.token)
alert('sucess');
}).catch(error => {
alert(JSON.stringify(error.response, 'catch'));
});
}
After the storing a token in async storage next api will call with auth token
Related
I am developing a mobile application with React Native. With this application, I connect to salesforce and make transactions.
I created Platform Events on Salesforce side and I want React Native Component to subscribe to it.
I can't use lightning/empApi or CometD because I don't code web. According to the document, my only option is Pub/Sub API.
I tried to pull it directly with FETCH but with no result.
import {View, Text} from 'react-native';
import React, { useEffect, useState } from 'react';
import { Force, oauth } from 'react-native-force';
function History() {
const [session, setSession] = useState()
const eventName = "Test_PE__e";
const replayId = -1;
const [subscription, setSubscription] = React.useState();
useEffect(() => {
oauth.getAuthCredentials(
(data) => console.log(data), // already logged in
() => {
oauth.authenticate(
() => setSession(data),
(error) => console.log('Failed to authenticate:' + error)
);
});
},[]);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text> Subscribed to {eventName} </Text>
</View>
);
async function setPEvents(session) {
const headers = new Headers({
'Authorization': `Bearer ${session.accessToken}`,
'Content-Type': 'application/json'
});
const body = {
"event": `/event/${eventName}`,
"replayId": replayId
};
const url = `${session.instanceUrl}/services/data/v57.0/event/${eventName}/subscriptions`;
const requestOptions = {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
};
const resp = await fetch(url, requestOptions)
.then(async (response) => {
console.log(response);
return await response.json();
})
.catch(error => console.log('Error:', error));
setSubscription(resp);
console.log("FIRATTT");
console.log("Result:",resp);
}
}
export default History;
What can I do to subscribe?
Or how can I use the SalesForce Pub/Sub API in React Native?
I'm trying to build on the example app provided by livekit, so far I've implemented everything like the example app and I've been successful with connecting to a room on example website, I recieve audio from website, but I don't read the video stream, and I also can't send audio or video at all.
Steps to reproduce the behavior:
add the following to index.js
import { registerRootComponent } from "expo";
import { registerGlobals } from "livekit-react-native";
import App from "./App";
registerRootComponent(App);
registerGlobals();
Rendering the following component in App.tsx
import { Participant, Room, Track } from "livekit-client";
import {
useRoom,
useParticipant,
AudioSession,
VideoView,
} from "livekit-react-native";
import { useEffect, useState } from "react";
import { Text, ListRenderItem, StyleSheet, FlatList, View } from "react-native";
import { ParticipantView } from "./ParticipantView";
import { RoomControls } from "./RoomControls";
import type { TrackPublication } from "livekit-client";
const App = () => {
// Create a room state
const [, setIsConnected] = useState(false);
const [room] = useState(
() =>
new Room({
publishDefaults: { simulcast: false },
adaptiveStream: true,
})
);
// Get the participants from the room
const { participants } = useRoom(room);
const url = "[hard-coded-url]";
const token =
"[hard-coded-token";
useEffect(() => {
let connect = async () => {
// If you wish to configure audio, uncomment the following:
await AudioSession.configureAudio({
android: {
preferredOutputList: ["speaker"],
},
ios: {
defaultOutput: "speaker",
},
});
await AudioSession.startAudioSession();
await room.connect(url, token, {});
await room.localParticipant.setCameraEnabled(true);
await room.localParticipant.setMicrophoneEnabled(true);
await room.localParticipant.enableCameraAndMicrophone();
console.log("connected to ", url);
setIsConnected(true);
};
connect();
return () => {
room.disconnect();
AudioSession.stopAudioSession();
};
}, [url, token, room]);
// Setup views.
const stageView = participants.length > 0 && (
<ParticipantView participant={participants[0]} style={styles.stage} />
);
const renderParticipant: ListRenderItem<Participant> = ({ item }) => {
return (
<ParticipantView participant={item} style={styles.otherParticipantView} />
);
};
const otherParticipantsView = participants.length > 0 && (
<FlatList
data={participants}
renderItem={renderParticipant}
keyExtractor={(item) => item.sid}
horizontal={true}
style={styles.otherParticipantsList}
/>
);
const { cameraPublication, microphonePublication } = useParticipant(
room.localParticipant
);
return (
<View style={styles.container}>
{stageView}
{otherParticipantsView}
<RoomControls
micEnabled={isTrackEnabled(microphonePublication)}
setMicEnabled={(enabled: boolean) => {
room.localParticipant.setMicrophoneEnabled(enabled);
}}
cameraEnabled={isTrackEnabled(cameraPublication)}
setCameraEnabled={(enabled: boolean) => {
room.localParticipant.setCameraEnabled(enabled);
}}
onDisconnectClick={() => {
// navigation.pop();
console.log("disconnected");
}}
/>
</View>
);
};
function isTrackEnabled(pub?: TrackPublication): boolean {
return !(pub?.isMuted ?? true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
stage: {
flex: 1,
width: "100%",
},
otherParticipantsList: {
width: "100%",
height: 150,
flexGrow: 0,
},
otherParticipantView: {
width: 150,
height: 150,
},
});
export default App;
the components used here are mostly the same as what's in the example, I've removed the screensharing logic and the messages
5. I run the app using an expo development build
6. it will log that it's connected, you'll be able to hear sound from the remote participant, but not see any video or send any sound.
7. if i try to add
await room.localParticipant.enableCameraAndMicrophone();
in the useEffect, I get the following error:
Possible Unhandled Promise Rejection (id: 0):
Error: Not implemented.
getSettings#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:103733:24
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120307:109
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21932:14
tryCallTwo#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26656:9
doResolve#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26788:25
Promise#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26675:14
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21924:25
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120173:52
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
tryCallOne#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26648:16
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26729:27
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27687:26
_callTimer#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27602:17
_callReactNativeMicrotasksPass#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27635:17
callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27799:44
__callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21006:46
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20806:45
__guard#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20986:15
flushedQueue#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20805:21
flushedQueue#[native code]
Expected behavior
This should both receive & send video and audio streams between the two clients
enter image description here
Above is the image description of what I want to achieve. I already implemented all the layers but I have a problem in automatically updating userContext. I have to refresh the userContext.js page manually to all the information across the app get updated as I want.
My DataBase.js looks like this
import React, { createContext, useState, useEffect,useCallback} from "react";
// create context
const UserContext = createContext();
const UserContextProvider = ({children}) => {
// the value that will be given to the context
var data = global.userSignedUp
const [UserDetails, SetUserDetails] = useState(data)
const [loadingUser, setLoadingUser] = useState(true);
// fetch a user from a fake backend API
const fetchUser = async () => {
// this would usually be your own backend, or localStorage
// for example
var name = global.userSignedUp.username
var index= global.userSignedUp.id
console.log('This the response from DataBase.js',UserDetails)
const data= await fetch('XXXXXX/api/userprofile/'+UserDetails.id+'/',{
method : 'GET',
header : {
Accept : 'application/json',
'Content-Type' : 'application/json'
}
}).then(async res =>{
const response =await res.json()
console.log('This the response from DataBase.js',response)
SetUserDetails(response)
})
//
};
useEffect(() => {
fetchUser();
}, []);
return (
// the Provider gives access to the context to its children
<UserContext.Provider value={[UserDetails, SetUserDetails]}>
{children }
</UserContext.Provider>
);
};
export { UserContext, UserContextProvider };
I defined one global variable index that get updated depending on the user ID from the sign in page and passed inside the Database.js
const onSignInPressed =(logindata)=>{
const username = logindata.username
const password =logindata.password
// state={
// credentials :{username : username, password: password}
// }
fetch('http://XXXXX/auth/',{
method:'POST',
headers:{'Content-Type':'application/json'},
body : JSON.stringify({username:username, password:password})
}).then (async data =>{
const DataResponse =await data.json()
//console.log(DataResponse)
if (data.status===200){
fetch('http://XXXX/api/userprofile',{
method : 'GET',
header : {
Accept : 'application/json',
'Content-Type' : 'application/json'
}
}).then(async res =>{
const response =await res.json()
for (let i=0; i < response.length;i++){
if (response[i].user=== username){
userSignedUp=response[i]
console.log('this is the user Signed up Id',userSignedUp)
navigation.navigate('HomeProfile')
;
}
}
})
}
else{
Alert.alert('Invalid User!','Username or password is incorrect,')
}
})
}
in my HomeProfile.js I can get all the data from UserContext and it workds fine.
Now in my EditProfile.js I have this :
import React , {useState,useContext,useEffect,useCallback} from 'react'
import {SocialIcon} from 'react-native-elements'
import { ImageBackground, View, Text, Image, StyleSheet, useWindowDimensions,Alert} from 'react-native'
import { icons,images, COLORS, SIZES } from '../constants';
import {CustomInput} from '../Component/CustomInput';
import CustomButton from '../Component/CustomButton';
import {useNavigation} from '#react-navigation/native';
import {useForm, Controller} from 'react-hook-form';
import { UserContext, UserContextProvider } from "./MobileDatabase/DataBase";
const EditProfile = () => {
return (
<UserContextProvider>
<EditProfilePage />
</UserContextProvider>
);
}
const EditProfilePage = () => {
const {control,handleSubmit,watch} = useForm();
const {height}= useWindowDimensions();
const navigation =useNavigation();
const newpwd = watch('NewPassword')
const [UserDetails, SetUserDetails]= useContext(UserContext);
let OldUsername=UserDetails.user
let DataFromServer=UserDetails
const onSavePressed = async (EditData) =>{
console.log(EditData)
const uploadData =new FormData();
uploadData.append('username',EditData.ChangeUsername)
let editData= await fetch('http://192.168.56.1:8000/api/users/'+OldUsername+'/',{
method:'PATCH',
headers:{Accept: 'application/json',
'Content-Type': 'multipart/form-data; '},
body :uploadData,
})
let EditDataResponseJson = await editData.json();
console.log(EditDataResponseJson)
SetUserDetails({...UserDetails, user:EditDataResponseJson.username})
UserContextProvider(EditDataResponseJson)
navigation.navigate('HomeProfile')
}
return (
<View style={styles.root}>
<Image
source ={{uri:UserDetails.Profileimage}}
style={[styles.logo]}
//resizeMode='contain'
/>
<Text style={{fontWeight:'bold',
//position:"absolute",
flex:1,
fontSize: 20,
top:'3%',
maxWidth:200,
alignSelf:'center' }}>{UserDetails.user}</Text>
<CustomInput placeholder ='Change UserName'
name="ChangeUsername"
control={control}
rules={{required: 'Username is required',
minLength:{
value:3,
message :'Username should be at least 3 characters long'
}
}}
// value={username}
// setValue={setUsername}
/>
<CustomInput placeholder= 'Change Password'
name ='NewPassword'
control={control}
rules={{required: 'New password is required'}}
// value={password}
// setValue={setPassword}
secureTextEntry={true}
/>
<CustomInput placeholder= 'Confirm Password'
name ='RepeatNewPassword'
control={control}
rules={{
validate: value => value === newpwd || 'Password do not match'
}}
// value={password}
// setValue={setPassword}
secureTextEntry={true}
/>
<View style ={styles.Signup}>
<CustomButton text= 'Save Changes' onPress={handleSubmit(onSavePressed)} />
</View>
</View>
)
}
const styles = StyleSheet.create({
root :{
//alignItems :'center',
paddingTop :'60%',
flex: 1,
},
cover:{
flex:1,
justifyContent: 'center',
},
logo:{
position :'absolute',
top:'10%',
alignSelf:'center',
justifyContent:'center',
alignItems: 'center',
width: 150,
height: 150,
borderRadius: 400/ 2,
},
Signup:{
marginTop: '20%',
}
})
export default EditProfile
When I update the Username for example, it only changes inside EditPage.js but not in HomeProfile.js event thought I update the SetUserDetails. The only way to see the updated data is to refresh the Database.js.
I am very much stuck since a month now and hope for a help here.
Thank you!!
i build an application with reactNative and Expo for front-end and django for back-end
i want take token from AsyncStorage to recognised the user, but the is an errors
Warning: An unhandled error was caught from submitForm(), [ReferenceError: Can't find variable: useState]
when i change the owner id to static value the submit works fine and show the token value on the console log not sure where is the issue exactly
import React, {useState} from 'react';
import { FieldArray, Formik } from "formik";
import axios from "axios";
import AsyncStorage from '#react-native-async-storage/async-storage';
import jwt_decode from "jwt-decode";
function AddScreen(props){
const submit = ({ type, category, amount }) => {
//here you define the token to be set
const [token, setToken] = useState();
//here you get the token from AsyncStorage
const getToken = async () => {
try {
const data = await AsyncStorage.getItem('token');
if (data !== null) {
setToken(data)
return data;
}
} catch (error) {
console.log(error);
}
};
//here you set the token
getToken()
//here you decode the token
const tokens = token;
const decoded = jwtDecode(tokens);
//here you get the id and it returns a number
const id = decoded.user_id
const config = {
headers: {
"Content-Type": "application/json",
},
};
const date = Date.now();
const owner = id;
const body = JSON.stringify({ type, category, amount, date, owner });
if (type == "" || category == "" || amount == "") {
alert("Please Enter all details");
return;
}
// 'http://192.168.8.143:8000/transactions/'
axios
.post("http://192.168.8.143:8000/transactions/", body, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
};
return (
<View style={{ flex: 1, backgroundColor: COLORS.gray }}>
<Formik
initialValues={{ type: "", category: "", amount: "" }}
onSubmit={(values) => {
submit(values);
}}
>
{(props) => (
<View style={styles.whitecard}>
<TextInput
style={styles.inputstyle}
placeholder="type"
onChangeText={props.handleChange("type")}
value={props.values.type}
/>
<TextInput
style={styles.inputstyle}
placeholder="category"
onChangeText={props.handleChange("category")}
value={props.values.category}
/>
<TextInput
style={styles.inputstyle}
placeholder="amount"
onChangeText={props.handleChange("amount")}
value={props.values.amount}
keyboardType="numeric"
/>
<View
style={{
margin: 10,
padding: 0,
backgroundColor: COLORS.pink,
borderRadius: 6,
}}
>
<Button
title="Submit"
color="white"
onPress={props.handleSubmit}
></Button>
</View>
</View>
)}
</Formik>
</View>
);
};
...
export default AddScreen;
the error show
Warning: An unhandled error was caught from submitForm(), [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.]
You are not importing UseState from React. Also you need to convert your code into a react functional component.
EDIT
For your new error, you need to move the useState out of submit. It must be at the root level of the functional component. I am updating the code example below as well.
import React, {useState} from 'react';
//All your other imports
function AddScreen(props) {
const [token, setToken] = useState(null);
//Everything else remains same inside
};
i am a beginner in react native. my problem is, i am trying to send image from camera to aws s3. this is my latest code.
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Button, Image } from 'react-native';
import ImagePicker from 'react-native-image-picker';
import { RNS3 } from 'react-native-aws3';
import fs from 'react-native-fs';
import Buffer from 'buffer';
import AWS from 'aws-sdk';
function uploadToS3(image){
const filename = "the_file.jpeg";
const options = {
keyPrefix: "uploads/",
bucket: "this is bucketname",
region: "this is region",
accessKey: "this is access key",
secretKey: "this is secret key",
successActionStatus: 201
}
try{
const s3 = new AWS.S3({accessKeyId: options.accessKey, secretAccessKey:options.secretKey, region:options.region});
var UploadURL;
const params = {Bucket: options.bucket, Key: options.keyPrefix+filename, ContentType: image.type};
s3.getSignedUrl('putObject', params, function (err, url) {
console.log('Your generated pre-signed URL is', url);
UploadURL = url;
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log("ok: ", xhr.response);
alert("success");
} else {
console.log("no: " , xhr.response);
alert("no");
}
}
}
xhr.open('PUT', UploadURL)
xhr.setRequestHeader('Content-Type', image.type)
xhr.send({image})
});
} catch(error){
console.log("err : ",error)
}
}
class HomeScreen extends React.Component {
constructor(props) {
global.currentScreenIndex = 'HomeScreen';
super(props);
this.state = {
resourcePath: {},
requestStatus: {},
employees: {},
response: {},
};
}
cameraLaunch = (id) => {
console.log(id);
let options = {
title: 'Select Picture',
storageOptions: {
skipBackup: true,
path: 'images',
},
base64: true,
maxWidth: 400,
maxHeight: 400
};
ImagePicker.launchCamera(options, (res) => {
//console.log('Response = ', res);
if (res.didCancel) {
console.log('User cancelled image picker');
} else if (res.error) {
console.log('ImagePicker Error: ', res.error);
} else if (res.customButton) {
console.log('User tapped custom button: ', res.customButton);
alert(res.customButton);
} else {
let source = res;
this.setState({
resourcePath: source,
});
uploadToS3(res);
}
});
}
render(){
return (
<View style={{ flex: 1, alignItems: 'center', marginTop: 100 }}>
<Button
onPress={()=>this.cameraLaunch(1)}
title="OpenCamera"
color="#841584"
/>
<Text style={{ alignItems: 'center' }}>
{this.state.resourcePath.uri}
</Text>
<Image source={this.state.resourcePath} />
</View>
);
}
};
export default HomeScreen;
there is nothing wrong with the camera or presigned url generation. if run, there will be the_file.jpeg in "this is bucket name"/uploads/the_file.jpeg, but the problem is, its size is 0 byte. i have tried to send just image.data, but apparently it just make the_file.jpeg become a "txt file" with "jpeg" extension. please help.
ps : i am aware on how insecure this code.
It looks like you missed the purpose of presigned URLs which is to upload objects without the need of AWS credentials. In your example, you are initializing the S3 client using the AWS credential, in that case, you can simply use s3.upload function to upload your file.
I had the same issue and nothing helped. This is what I did.
Make sure you follow the amplify guide for setting up a app. amplify init, amplify add auth, amplify push, and then amplify add storage and then do this.
import Amplify, { Storage } from 'aws-amplify'
import config from './src/aws-exports'
// import awsconfig from './aws-exports';
// Might need to switch line 7 to awsconfig
Amplify.configure(config)
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { Button, Image, View, Platform, StyleSheet, Text, TextInput } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
function App() {
const [image, setImage] = useState(null)
const [name, setName] = useState('Evan Erickson')
useEffect(() => {
(async () => {
if (Platform.OS !== 'web') {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
}
}
})();
}, []);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result)
async function pathToImageFile(data) {
try {
const response = await fetch(data);
const blob = await response.blob();
await Storage.put(`customers/${name}`, blob, {
contentType: 'image/jpeg', // contentType is optional
});
} catch (err) {
console.log('Error uploading file:', err);
}
}
// later
pathToImageFile(result.uri);
}
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Pick an image from camera roll" onPress={pickImage} />
{image && <Image source={{ uri: image }} style={{ width: 200, height: 200 }} />}
<Button title="Upload image" onPress={() => {alert(image)}} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default withAuthenticator(App)