I'm trying to implement a Sign In to Google from a React-native app. I found this question where someone give a way to do it, but is not working anymore or I'm doing something wrong.
My code is this one:
App.js
"use strict";
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { LoginGoogle } from './src/components/Login.js';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open uuuup App.js ehh to start working on your app!</Text>
<LoginGoogle/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Login.js
"use strict";
import React, { Component } from 'react';
import Expo from 'expo';
import Button from 'react-native';
import { Text, View } from 'react-native';
class LoginGoogle extends Component {
signInWithGoogleAsync = async () => {
try {
const result = await Expo.Google.logInAsync({
androidClientId: process.env.GOOGLE_ANDROID_CLIENT_ID,
iosClientId: process.env.GOOGLE_IOS_CLIENT_ID,
scopes: ['profile'],
})
if (result.type === 'success') {
return result
}
return { cancelled: true }
} catch (e) {
return { error: e }
}
}
onLoginPress = async () => {
const result = await this.signInWithGoogleAsync()
// if there is no result.error or result.cancelled, the user is logged in
// do something with the result
}
render() {
return (<Button onPress={this.onLoginPress}>Login</Button>)
}
}
export default LoginGoogle;
When this is compiled, it says the following error:
Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: undefinded. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports
I already found when this error generally happen as states this other question. I already try importing LoginGoogle with and without curly braces, but without luck.
Any idea on what could be happening here? I know that if I put only a Text in LoginGoogle.js and import it from App.js works like a charm, so probably it has something to do with the functions that are related to Google Sign In, but it's a guess, I could be wrong.
You only need to change this line:
import { LoginGoogle } from './src/components/Login.js';
to
import LoginGoogle from './src/components/Login.js';
The first line would work if you exported Login like this:
export {LoginGoogle}
and not
export default LoginGoogle;
Related
I have a problem with react-native, I am trying to login with facebook using the expo-facebook and firebase libraries, it loads everything well and it starts session well, but when it loads the following screen the following comes up:
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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://facebook.com/react-invalid-hook-call for tips about how to debug and fix this problem.
Code:
import React, { Component } from 'react'
import { View, Button, Text, StatusBar, LayoutAnimation, Image, StyleSheet } from 'react-native'
import { Toast } from 'native-base'
import * as Facebook from 'expo-facebook'
import * as firebase from 'firebase'
const app = {
id: APP_ID,
name: APP_NAME,
}
export default class LoginScreen extends Component {
static navigationOptions = {
header: null,
}
facebook = async () => {
Facebook.initializeAsync(app.id, app.name)
const { type, token } = await Facebook.logInWithReadPermissionsAsync(app.id, {
permission: 'public_profile',
})
if ( type == "success" ) {
const credential = firebase.auth.FacebookAuthProvider.credential( token )
firebase.auth().signInWithCredential(credential)
.catch(e => {
console.log(e)
})
}
this.props.navigation.navigate('App')
}
render() {
LayoutAnimation.easeInEaseOut()
return <View>
<Button title="Log in with facebook" style={styles.button} onPress={this.facebook}>
</Button>
</View>
}
}
Here is an image of error:
I have been having this error for hours and I don't know how to fix it, it's driving me crazy. In this shortcode here, I keep getting this error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
import * as Font from 'expo-font';
import React, {Component} from "react";
import { ActivityIndicator } from 'react-native'
import {Application} from "./src/Application.js";
class App extends Component {
constructor() {
super();
this.state = {
isReady: false,
};
}
componentWillMount = async() => {
await Font.loadAsync({
Roboto: require('./node_modules/native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('./node_modules/native-base/Fonts/Roboto_medium.ttf')
});
this.setState({isReady: true,});
};
render() {
if (!this.state.isReady) {
return <ActivityIndicator />
}
return (
<Application/>
);
}
}
export default App;
The error pointed to _callee$ in 18:16, which is this line
this.setState({isReady: true,});
What could be causing this and a possible solution?
I tried importing import {Application} from "./src/Application.js" without {} before, but it also returned the error of
Check the render method of _default
Edited: Added "Application.js"
import React from 'react';
import Root from "native-base";
import { createAppContainer } from '#react-navigation/native';
import { createStackNavigator } from 'react-navigation-stack';
import { createDrawerNavigator } from 'react-navigation-drawer';
import Home from "./screens/home/index";
import Email from "./screens/email/index";
import ProfileScreen from "./screens/ProfileScreen";
import SideBar from "./screens/SideBar/SideBar";
const Drawer = createDrawerNavigator(
{
Home: { screen: Home},
//Email: { screen: Email},
ProfileScreen: { screen: ProfileScreen}
},
{
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63"
},
contentComponent: props => <SideBar {...props}/>
}
);
const AppNavigator = createStackNavigator (
{
Drawer: {screen: Drawer}
},
{
initialRouteName: "Drawer",
headerMode: "none"
}
);
const AppContainer = createAppContainer(AppNavigator);
export default () =>
<Root>
<AppContainer/>
</Root>
With this statement,
export default () =>
<Root>
<AppContainer/>
</Root>
Without parentheses,it will interpreted as
export default () =>();
<Root>
<AppContainer/>
</Root>
So,it will return undefined which is not valid react element.Because of this above error will occur.
wrap the export default statement with ().It should be
export default () =>(
<Root> <AppContainer/></Root>
);
OR
export default () =>( <Root> <AppContainer/></Root> );
And import should be
import Application from "./src/Application";
Try
import * as Application from './src/application.js';
You are not exporting a named item but just a function byt you are trying to import a named item.
Check that you are exporting Application correctly from Application.js.
It should just be "export Application".
You are probably importing your components the wrong way.
How are you exporting Application in Application.js ?
Maybe remove {} will fix it
import Application from "./src/Application.js";
There is two ways you can export/import
export function ...
// another file
import {...} from '...'
Or using the default export
export default function ...
// another file
import ... from '...'
If you want to import it like
import {Application} from "./src/Application.js";
You should be exporting it like
export function Application...
And if you look ate what the error says...
...You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
I am trying to create a react-native application, I'm currently at the starting point and I cannot understand an issue that I encountered.
I need to integrate i18next for translations. I did this by following their step-by-step tutorial
I have the following code
App.js
import React, { Suspense, Component } from 'react';
import { ScrollView, StyleSheet, Text, View, } from 'react-native';
import { useTranslation } from 'react-i18next';
import { Colors, } from 'react-native/Libraries/NewAppScreen';
const MyComponent = () => {
const { t, i18n } = useTranslation();
return <Text>{t('index.welcome')}</Text>;
};
const App = () => {
return (
<Suspense fallback="loading">
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View style={styles.body}>
<MyComponent />
</View>
</ScrollView>
</Suspense>
);
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
body: {
backgroundColor: Colors.white,
},
});
export default App;
The issue here is that I get an Invariant Violation: Text strings must be rendered within a <Text> component error
If I change MyComponent to the following the application works
const MyComponent = () => {
return <Text>Anything</Text>;
};
So the issue here for me seems to be the useTranslation() hook.
What am I missing here?
LE
I was missing the namespace in the useTranslation()
I've added it useTranslations('translation') but still I have the same issue
The issue seems to be with the path for the translation files which cannot be parsed
i18next::backendConnector: loading namespace translation for language en failed failed parsing /translations/en/translation.json to json
In React the files would be public available via the public folder, in React-Native how should this be used? I think that the app cannot access that folder, where should the folder be placed?
LE2
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-xhr-backend';
i18n
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
backend: {
loadPath: '/translations/{{lng}}/{{ns}}.json',
},
});
export default i18n;
And the translations folder is placed in the root of the project
I started a new project with react-native. I created a component called Home.jsx in app/components/home/. It looks like this:
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
export default class Home extends Component {
render() {
return (
<View style={styles.container}>
<Text>This is the home component!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default Home;
And my index.js (in the root) file looks like this:
import {AppRegistry} from 'react-native';
import Home from './app/components/home/Home';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => Home);
When I try to load up the app in the the emulator, I get this error message:
error: bundling failed: Error: Unable to resolve module
`./app/components/home/Home` from
`/Users/[my_name]/repos/[repo_name]/index.js`:
The module `./app/components/home/Home` could not be found from
`/Users/[my_name]/repos/[repo_name]/index.js`. Indeed, none of these
files exist:
What am I doing wrong?
I got it working by not using a folder called app and instead using src. I'm not entirely sure why this solved the issue but there we go!
I have been working on this problem for two days now and nothing on the web seems to be exactly what I am looking for.
I am attempting to implement a StackNavigator into my React Native app, but for some reason "navigation" is not being passed as a prop to the involved components. Therefore when I call this.props.navigation.navigator by pressing Button, I get the error undefined is not an object (evaluating this.props.navigation.navigate).
I have logged the props several times and the props object is empty, so the issue is not a deconstruction-of-the-props-object issue like others who get this error have had, but the fact that the navigation prop is not there in the first place.
I've tried placing the navigator code in its own file and in the App.js file thinking that it was somehow called after the components are rendered, and therefore not getting a chance to pass the navigation prop in, but that didn't work either. I've also looked to see if it is part of the props in the componentDidMount event. Still not.
import React, { Component } from 'react'
import { Text, View, Button, StyleSheet, FlatList } from 'react-native'
import { StackNavigator } from 'react-navigation'
import { getDecks } from '../utils/api'
import NewDeckView from './NewDeckView'
import DeckListItem from './DeckListItem'
export default class DeckListView extends Component {
constructor(props){
super(props)
this.state = {
decks: []
}
}
componentDidMount(){
console.log('props now test',this.props)
getDecks()
.then( result => {
const parsedResult = JSON.parse(result);
const deckNames = Object.keys(parsedResult);
const deckObjects = [];
deckNames.forEach( deckName => {
parsedResult[deckName].key = parsedResult[deckName].title
deckObjects.push(parsedResult[deckName])
})
this.setState({
decks:deckObjects
})
} )
}
render(){
return (
<View style={styles.container}>
<Text style={styles.header}>Decks</Text>
<FlatList data={this.state.decks} renderItem={({item})=><DeckListItem title={item.title} noOfCards={item.questions?item.questions.length:0}/>} />
<Button styles={styles.button} title="New Deck" onPress={()=>{this.props.navigation.navigate('NewDeckView')}}/>
</View>
)
}
}
const styles = StyleSheet.create({
header:{
fontSize:30,
margin:20,
},
container:{
flex:1,
justifyContent:'flex-start',
alignItems:'center'
},
button:{
width:50
}
})
const Stack = StackNavigator({
DeckListView : {
screen: DeckListView,
},
NewDeckView: {
screen:NewDeckView,
}
})
Like Vicky and Shubhnik Singh mentioned, you need to render the imported navigation stack in App.js like so:
import React from 'react';
import { Stack } from './navigator/navigator'
export default class App extends React.Component {
render() {
return <Stack/>
}
}
The navigator should look something like this and the first key in the object passed to StackNavigator will be rendered by default. In this case, it will be DeckListView.
import { StackNavigator } from 'react-navigation'
import DeckListView from '../components/DeckListView'
import NewDeckView from '../components/NewDeckView'
export const Stack = StackNavigator({
DeckListView : {
screen: DeckListView,
navigationOptions: {
headerTitle: 'Home',
},
},
NewDeckView: {
screen:NewDeckView,
navigationOptions: {
headerTitle: 'New Deck',
},
},
})
Thanks guys for the support! Somehow this wasn't clear for me in the documentation.