Amplify Tutorial (Expo) and got error message on signin - react-native

I'm doing this tutorial: https://docs.amplify.aws/start/getting-started/auth/q/integration/react-native#create-login-ui
I followed it completely and did everything they told me to do. The Todo works, but when I added Auth, and wrapped it. The project will start. Users can create accounts. But when you try to sign in on iOS it won't work. Strangely, when I tested it on web, users could sign in. Leading me to think it is a problem with iOS. I tested it on my iPhone with expo installed and it failed there too.
Here is a link to my issue: https://github.com/aws-amplify/amplify-js/issues/8113#issuecomment-830995508
This is my app.js
import config from './aws-exports'
Amplify.configure(config)
import { withAuthenticator } from 'aws-amplify-react-native'
import React, { useEffect, useState } from 'react'
import {
View, Text, StyleSheet, TextInput, Button
} from 'react-native'
import { API, graphqlOperation } from 'aws-amplify'
import { createTodo } from './graphql/mutations'
import { listTodos } from './graphql/queries'
const initialState = { name: '', description: '' }
const App = () => {
const [formState, setFormState] = useState(initialState)
const [todos, setTodos] = useState([])
useEffect(() => {
fetchTodos()
}, [])
function setInput(key, value) {
setFormState({ ...formState, [key]: value })
}
async function fetchTodos() {
try {
const todoData = await API.graphql(graphqlOperation(listTodos))
const todos = todoData.data.listTodos.items
setTodos(todos)
} catch (err) { console.log('error fetching todos') }
}
async function addTodo() {
try {
const todo = { ...formState }
setTodos([...todos, todo])
setFormState(initialState)
await API.graphql(graphqlOperation(createTodo, {input: todo}))
} catch (err) {
console.log('error creating todo:', err)
}
}
return (
<View style={styles.container}>
<TextInput
onChangeText={val => setInput('name', val)}
style={styles.input}
value={formState.name}
placeholder="Name"
/>
<TextInput
onChangeText={val => setInput('description', val)}
style={styles.input}
value={formState.description}
placeholder="Description"
/>
<Button title="Create Todo" onPress={addTodo} />
{
todos.map((todo, index) => (
<View key={todo.id ? todo.id : index} style={styles.todo}>
<Text style={styles.todoName}>{todo.name}</Text>
<Text>{todo.description}</Text>
</View>
))
}
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', padding: 20 },
todo: { marginBottom: 15 },
input: { height: 50, backgroundColor: '#ddd', marginBottom: 10, padding: 8 },
todoName: { fontSize: 18 }
})
export default withAuthenticator(App)```
I feel like the problem might be with the ./aws-exports potentially. There was a bug where you had to move it out of src, etc. Anyone have any ideas?
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/1Wt6J.png

I found out that the login error was due to a bug with expo deprecating a file. See this issue for more. https://github.com/aws-amplify/amplify-js/issues/8113#issuecomment-830995508

Related

Errors with reactNative/voice in expo

thats my code
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, Button, View } from 'react-native';
import { useEffect, useState } from 'react';
import Voice from '#react-native-voice/voice';
export default function App() {
let [started, setStarted] = useState(false);
let [results, setResults] = useState([]);
useEffect(() => {
Voice.onSpeechError = onSpeechError;
Voice.onSpeechResults = onSpeechResults;
return () => {
Voice.destroy().then(Voice.removeAllListeners);
}
}, []);
const startSpeechToText = async () => {
await Voice.start();
setStarted(true);
};
const stopSpeechToText = async () => {
await Voice.stop();
setStarted(false);
};
const onSpeechResults = (result) => {
setResults(result.value);
};
const onSpeechError = (error) => {
console.log(error);
};
return (
<View style={styles.container}>
{!started ? <Button title='Start Speech to Text' onPress={startSpeechToText} /> : undefined}
{started ? <Button title='Stop Speech to Text' onPress={stopSpeechToText} /> : undefined}
{results.map((result, index) => <Text key={index}>{result}</Text>)}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
when I run it I keep getting this error
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'Voice.startSpeech')]
I tried asking chatGPT but he can't answer it
Packages and import is correct, so I don't know what the error is nor how I can fix it
Check if it works on another version of android, I launched some emulators and it seems that below Android 12 there are problems with Permissions.
On Android 12 and above, my code with react-native-voice works well with expo run:android but I can't find out why once built with expo build:android I still have problems with mic permissions

AsyncStorage doesn't save onboarding when closing react native app

Well, I made a presentation onboarding screen, as soon as the user opens the app, the screen is shown, but I want this to be saved using AsyncStorage, if I close and open the app, the onboarding screen is not shown, but the screen of login.
I did all the code but nothing happens and the screen is displayed every time I close and open the app, I don't know what I'm doing wrong, code below.
App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import {AuthProvider} from './src/providers/Auth';
import AsyncStorage from '#react-native-async-storage/async-storage';
import { OnBoarding } from './src/screen/OnBoarding';
import { SignIn } from './src/screen/SignIn';
import { HomeScreen } from './src/screen/HomeScreen';
import { ActivityIndicator } from 'react-native';
const Stack = createNativeStackNavigator();
const Loading = () => {
return (
<View>
<ActivityIndicator size="large" />
</View>
);
}
export function App(){
const [loading, setLoading] = useState(true);
const [viewedOnboarding, setViewedOnboarding] = useState(false);
useEffect(() => {
checkOnBoarding();
}, [])
const checkOnBoarding = async () => {
try{
const value = await AsyncStorage.getItem('#viewedOnboarding');
if(value !== null){
setViewedOnboarding(true);
}
console.log(value);
}catch(err) {
console.log('Error #checkOnboarding: ', err);
}finally {
setLoading(false)
}
}
return (
<AuthProvider>
<NavigationContainer>
<Stack.Navigator
initialRouteName={loading ? <Loading /> : viewedOnboarding ? <HomeScreen /> : <OnBoarding />}
screenOptions={
{headerShown: false}
}
>
<Stack.Screen
name="SignIn"
component={SignIn}
/>
</Stack.Navigator>
</NavigationContainer>
</AuthProvider>
);
}
Onboarding.js
import React, { useEffect, useState } from 'react';
import {Text, View, StyleSheet, Image, TouchableOpacity, Button} from 'react-native';
import AppIntroSlider from 'react-native-app-intro-slider';
import Icon from 'react-native-vector-icons/FontAwesome';
import AsyncStorage from '#react-native-async-storage/async-storage';
const slides = [
{
key: 1,
title: 'Only Books Can Help You',
text: 'Books can help you to increase your knowledge and become more successfully.',
image: require('../../assets/imagem1.png'),
},
{
key: 2,
title: 'Learn Smartly',
text: 'It’s 2022 and it’s time to learn every quickly and smartly. All books are storage in cloud and you can access all of them from your laptop or PC.',
image: require('../../assets/imagem2.png'),
},
{
key: 3,
title: 'Learn Smartly',
text: 'It’s 2022 and it’s time to learn every quickly and smartly. All books are storage in cloud and you can access all of them from your laptop or PC.',
image: require('../../assets/imagem2.png'),
},
];
export function OnBoarding(){
function renderItem({item}){
return (
<View style={styles.container}>
<Image style={styles.image} source={item.image} />
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.content}>{item.text}</Text>
</View>
);
}
function _renderPrevButton() {
return (
<View style={styles.buttonCircle}>
<Icon
name="angle-left"
color="#000"
size={40}
/>
</View>
);
};
function _renderNextButton() {
return (
<View style={styles.buttonCircle}>
<Icon
name="angle-right"
color="#000"
size={40}
/>
</View>
);
};
const onPressFinish = async () => {
try{
await AsyncStorage.setItem('#viewedOnboarding', 'true')
navigation.navigate('SignIn');
}catch(err) {
console.log("Error #setitem ", err);
}
};
const renderDoneButton = () => {
return (
<TouchableOpacity onPress={onPressFinish}>
<Text style={{color: "#000"}}>Done</Text>
</TouchableOpacity>
);
};
return (
<AppIntroSlider
data={slides}
renderItem={renderItem}
keyExtractor={item => item.key}
renderPrevButton={_renderPrevButton}
renderNextButton={_renderNextButton}
renderDoneButton={renderDoneButton}
showPrevButton
showDoneButton
dotStyle={{backgroundColor: '#9D9D9D'}}
activeDotStyle={{backgroundColor: '#DE7773'}}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: "#fff"
},
title: {
color: "#292B38",
fontSize: 24,
fontWeight: 'bold',
marginTop: 50
},
content: {
color: "#4D506C",
textAlign: 'center',
padding: 25,
lineHeight: 18
},
image: {
width: 300,
height: 300,
},
button: {
color: "#000",
backgroundColor: "transparent"
}
})
Probably because of the async nature of AsyncStore when you open your app first you init viewedOnboarding with false, then start reading storage and then you check is onboarding done or not. And of course because storage is async first time you check in Navigation condition you always get
I have modified your checkOnBoarding function.
Here is the code:
const checkOnBoarding = () => {
try{
AsyncStorage.getItem('#viewedOnboarding').then(value => {
if(value !== null){
setViewedOnboarding(true);
}
console.log(value);
})
}catch(err) {
console.log('Error #checkOnboarding: ', err);
}finally {
setLoading(false)
}
}

react-native-image-crop-tools CropView not showing image to be cropped

I am using react-native-image-crop-tools for cropping the image but CropView not showing the image to be cropped only a blank screen is showing. any solution regarding this?
import { CropView } from 'react-native-image-crop-tools';
const [uri, setUri] = useState('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg');
{uri !== undefined && <CropView
sourceUrl={uri}
style={{flex:1}}
ref={cropViewRef}
onImageCrop={(res) => console.warn(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}
Try this, I hope it will help you.
app.js
import React, { useState, useRef } from 'react';
import { Button, StyleSheet, View} from 'react-native';
import { CropView } from 'react-native-image-crop-tools';
import { launchImageLibrary } from 'react-native-image-picker';
export default function app() {
const [uri, setUri] = useState();
const cropViewRef = useRef();
let options = {
mediaType: 'photo',
quality: 1,
};
return (
<>
<View style={styles.container}>
<Button
title={'Pick Image'}
onPress={() => {
launchImageLibrary(options, response => {
setUri(response.assets[0].uri);
});
}}
/>
{uri !== undefined && <CropView
sourceUrl={uri}
style={styles.cropView}
ref={cropViewRef}
onImageCrop={(res) => console.log(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}
<Button
title={'Get Cropped View'}
onPress={() => {
cropViewRef.current.saveImage(true, 100);
}}
/>
</View>
</>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
cropView: {
flex: 1,
backgroundColor: '#000'
},
});
The library doesn't support remote images. It working in iOS is merely coincidental as might the native ios library supports for the cropping of network images.
If you want to crop a remote image please download it first using RNFetchBlob and then pass the local file path to it.
Supporting remote images directly is a somewhat complicated task and out of scope for this project.
You also can check out the closed issue in the library.
https://github.com/hhunaid/react-native-image-crop-tools/issues/16
You can have a try with the below example to crop the network images in the android platform:
For ex:
import React, {useCallback, useEffect, useState} from 'react';
import {View, Text} from 'react-native';
import {CropView} from 'react-native-image-crop-tools';
import RNFetchBlob from 'rn-fetch-blob';
export default () => {
const [uri, setUri] = useState('');
const getImage = useCallback(() => {
try {
RNFetchBlob.config({
fileCache: true,
// by adding this option, the temp files will have a file extension
appendExt: 'png',
})
.fetch(
'GET',
'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg',
)
.then(res => {
let status = res.info().status;
if (status === 200) {
setUri('file://' + res.path());
} else {
console.log(status);
}
})
// Something went wrong:
.catch((errorMessage, statusCode) => {
// error handling
console.log('Error : ', errorMessage);
});
} catch (err) {
console.log('Error : ', err.message);
}
}, []);
useEffect(() => {
getImage();
}, [getImage]);
if (uri === '') {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>{'processing...'}</Text>
</View>
);
}
return (
<CropView
sourceUrl={uri}
style={{flex: 1, height: '100%', width: '100%'}}
// ref={cropViewRef}
onImageCrop={res => console.warn(res)}
keepAspectRatio
aspectRatio={{width: 16, height: 9}}
/>
);
};

Login google Auth in expo not working properly

when i press the sign in with google button it doesn't do anything
i followed https://docs.expo.io/versions/latest/sdk/google/
the iosClientId: 'my-id', is normally my google clientid but changed it for security reasons
import React, { Component } from 'react';
import {StyleSheet, Text, View, Button} from 'react-native';
class LoginScreen extends Component {
async signInWithGoogleAsync () {
try {
const result = await Expo.Google.logInAsync({
//androidClientId: YOUR_CLIENT_ID_HERE,
behavior: 'web',
iosClientId: 'my-id',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
return result.accessToken;
} else {
return { cancelled: true };
}
} catch (e) {
return { error: true };
}
}
render() {
return (
<View style={styles.container}>
<Button title={"Sign In With Google"}
onpress={() =>this.signInWithGoogleAsync()}
/>
</View>
);
}
}
export default LoginScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
}
});
I expect is when i press the Sign In With Google button it to let me sign in
but what im getting is the button not doing anything
Change your render function to this:
render() {
return (
<View style={styles.container}>
<Button title={"Sign In With Google"}
onPress={() =>this.signInWithGoogleAsync()}
/>
</View>
);
}

React Native Facebook Login using official fbsdk

I tried following the starter tutorial by setting up a new React Native Project for iOS. But the loginbutton doesn't seem to be working. Any help is appreciated.
Here's the index.ios.js:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
const FBSDK = require('react-native-fbsdk');
const {
LoginButton
} = FBSDK;
var Login = React.createClass({
render: function() {
return (
<View>
<LoginButton
publishPermissions={["publish_actions"]}
onLoginFinished={
(error, result) => {
if (error) {
alert("login has error: " + result.error);
} else if (result.isCancelled) {
alert("login is cancelled.");
} else {
alert("login has finished with permissions: " + result.grantedPermissions)
}
}
}
onLogoutFinished={() => alert("logout.")}/>
</View>
);
}
});
class AwesomeProject extends Component {
render() {
return (
<View style={styles.container}>
<Text>
Login to Facebook
</Text>
<Login />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
shareText: {
fontSize: 20,
margin: 10,
}
});
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
And the screenshot of the emulator:
You need to link the sdk's iOS project in your app's project.
If you're using react-native-sdk v0.2.0+, rnpm will take care of this step and you can follow the tips here to complete set up.
If you're using the older version, you need to link react-native-fbsdkxxx.xcodeproj in YourApp.xcodeproj. Follow the manual linking steps in https://facebook.github.io/react-native/docs/linking-libraries-ios.html