React native bottom navigation bar - javascript

Transition for google sign in to bottom bar navigation.
For ios and Android
I am following tutorials and creating a react native application that is using google sign in. After the user signs in, the users information is displayed, and there is a logout button. There is also a button that changes the screen the home screen and this is where I need help. I want to implement a bottom bar navigation. The code for the bottom bar navigation works fine, just do not know how to connect the screen from the successful google sign in, to the section of the bottom bar navigation.
my app.js code
//This is an example code for Navigator//
import React, { Component } from 'react';
//import react in our code.
//For react-navigation 4.0+
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createStackNavigator} from 'react-navigation-stack';
import { WebView } from 'react-native-webview';
import Ionicons from 'react-native-vector-icons/Ionicons';
import {createBottomTabNavigator} from 'react-navigation-tabs';
import SettingsScreen from './pages/SettingsScreen';
import DetailsScreen from './pages/DetailsScreen';
import ProfileScreen from './pages/ProfileScreen';
import LoginPage from './pages/LoginPage';
const App2 = createStackNavigator({
//Constant which holds all the screens like index of any book
LoginPage: { screen: LoginPage},
Home: { screen: HomeScreen },
},
{
initialRouteName: 'LoginPage',
}
);
const HomeStack = createStackNavigator(
{
//Defination of Navigaton from home screen
Home: { screen: HomeScreen },
Details: { screen: DetailsScreen },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Home',
//Header title
},
}
);
const SettingsStack = createStackNavigator(
{
//Defination of Navigaton from setting screen
Settings: { screen: SettingsScreen },
Details: { screen: DetailsScreen },
Profile: { screen: ProfileScreen },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Settings',
//Header title
},
}
);
const App = createBottomTabNavigator(
{
Home: { screen: HomeStack },
Settings: { screen: SettingsStack },
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let IconComponent = Ionicons;
let iconName;
if (routeName === 'Home') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
} else if (routeName === 'Settings') {
iconName = `ios-checkmark-circle${focused ? '' : '-outline'}`;
}
return <IconComponent name={iconName} size={25} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: '#42f44b',
inactiveTintColor: 'gray',
},
}
);
export default (App2)
/*
cd "/Users/carloscraig/rnNoExcusasNew" && npx react-native run-ios
cd "/Users/carloscraig/rnNoExcusasNew" && npx react-native run-android
*/
my loginpage.js
/*This is th Example of google Sign in*/
import React, { Component } from 'react';
import QRCode from 'react-native-qrcode-svg';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator} from 'react-navigation-stack';
import {
StyleSheet, ImageBackground, ScrollView, Dimensions,
Text,
View, StatusBar,
Alert,
Image,
ActivityIndicator,
TouchableOpacity,
} from 'react-native';
import {
GoogleSignin,
GoogleSigninButton,
statusCodes,
} from 'react-native-google-signin';
const { height } = Dimensions.get('window');
export default class LoginPage extends React.Component {
static navigationOptions = {
title: 'testing title',
//Sets Header text of Status Bar
headerStyle: {
backgroundColor: '#f4511e',
//Sets Header color
},
headerTintColor: '#fff',
//Sets Header text color
headerTitleStyle: {
fontWeight: 'bold',
//Sets Header text style
},
};
constructor(props) {
super(props);
this.state = {
userInfo: null,
gettingLoginStatus: true,
};
};
// For scrollView
state = {
// We don't know the size of the content initially, and the probably won't instantly try to scroll, so set the initial content height to 0
screenHeight: 0,
};
onContentSizeChange = (contentWidth, contentHeight) => {
// Save the content height in state
this.setState({ screenHeight: contentHeight });
};
componentDidMount() {
//initial configuration
GoogleSignin.configure({
//It is mandatory to call this method before attempting to call signIn()
scopes: ['https://www.googleapis.com/auth/drive.readonly'],
// Repleace with your webClientId generated from Firebase console
webClientId: '.com',
});
//Check if user is already signed in
this._isSignedIn();
}
_isSignedIn = async () => {
const isSignedIn = await GoogleSignin.isSignedIn();
//const { navigate } = this.props.navigation;
if (isSignedIn) {
alert('User is already signed in');
//Get the User details as user is already signed in
this._getCurrentUserInfo();
//navigate('Home')
} else {
alert("Please Login");
console.log('Please Login');
}
this.setState({ gettingLoginStatus: false });
};
_getCurrentUserInfo = async () => {
try {
const userInfo = await GoogleSignin.signInSilently();
console.log('User Info --> ', userInfo);
this.setState({ userInfo: userInfo });
} catch (error) {
if (error.code === statusCodes.SIGN_IN_REQUIRED) {
alert('User has not signed in yet');
console.log('User has not signed in yet');
} else {
alert("Something went wrong. Unable to get user's info");
console.log("Something went wrong. Unable to get user's info");
}
}
};
_signIn = async () => {
//Prompts a modal to let the user sign in into your application.
try {
await GoogleSignin.hasPlayServices({
//Check if device has Google Play Services installed.
//Always resolves to true on iOS.
showPlayServicesUpdateDialog: true,
});
const userInfo = await GoogleSignin.signIn();
console.log('User Info --> ', userInfo);
this.setState({ userInfo: userInfo });
} catch (error) {
console.log('Message', error.message);
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
console.log('User Cancelled the Login Flow');
} else if (error.code === statusCodes.IN_PROGRESS) {
console.log('Signing In');
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
console.log('Play Services Not Available or Outdated');
} else {
console.log('Some Other Error Happened');
}
}
};
_signOut = async () => {
//Remove user session from the device.
try {
await GoogleSignin.revokeAccess();
await GoogleSignin.signOut();
this.setState({ userInfo: null }); // Remove the user from your app's state as well
} catch (error) {
console.error(error);
}
};
render() {
const scrollEnabled = this.state.screenHeight > height;
//returning Loader untill we check for the already signed in user
if (this.state.gettingLoginStatus) {
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
} else {
if (this.state.userInfo != null) {
//Showing the User detail
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<StatusBar barStyle="light-content"></StatusBar>
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={styles.scrollview}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<ImageBackground source={require("/Users/carloscraig/rnNoExcusasNew/pages/assets/grassbcg2.png")}
style={{ width: '100%', height: '100%' }}>
<Image source={require("/Users/carloscraig/rnNoExcusasNew/pages/assets/noexlogo.png")}
style={styles.logo}>
</Image>
<Image
source={{ uri: this.state.userInfo.user.photo }}
style={styles.imageStyle}
/>
<Text style={styles.text}>
Name: {this.state.userInfo.user.name}{' '}
</Text>
<Text style={styles.text}>
Email: {this.state.userInfo.user.email}
</Text>
<View style={styles.qr}>
<QRCode
value= {this.state.userInfo.user.email}
size={200}
/>
</View>
<TouchableOpacity style={styles.button} onPress={this._signOut} >
<Text>Logout</Text>
</TouchableOpacity>
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={() =>navigate('Home')}>
<Text>Next Page</Text>
</TouchableOpacity>
</View>
</ImageBackground>
</ScrollView>
</View>
);
} else {
const scrollEnabled = this.state.screenHeight > height;
//For login showing the Signin button
return (
<View style={styles.container}>
<StatusBar barStyle="light-content"></StatusBar>
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={styles.scrollview}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<ImageBackground source={require("/Users/carloscraig/rnNoExcusasNew/pages/assets/grassbcg2.png")}
style={{ width: '100%', height: '100%' }}>
<Image source={require("/Users/carloscraig/rnNoExcusasNew/pages/assets/noexlogo.png")}
style={styles.logo}>
</Image>
<GoogleSigninButton
style={{ width: 312, height: 48 }}
size={GoogleSigninButton.Size.Wide}
color={GoogleSigninButton.Color.Light}
onPress={this._signIn}
/>
</ImageBackground>
</ScrollView>
</View>
);
}
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
width: null,
height: null,
},
imageStyle: {
width: 200,
height: 300,
resizeMode: 'contain',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 30,
marginBottom: 20,
},
scrollview: {
flexGrow: 1,
width: null,
height: null,
},
logo: {
width: 200,
height: 200,
marginTop: 40,
alignSelf: "center",
justifyContent: "center",
},
qr: {
marginTop: 20,
alignSelf: "center",
justifyContent: "center",
},
});
and lastly the homescreen.js
//This is an example code for Bottom Navigation//
import React from 'react';
//import react in our code.
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
//import all the basic component we have used
export default class extends React.Component {
//Home Screen to show in Home Option
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ marginTop: 50, fontSize: 25 }}>Home!</Text>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Settings')}>
<Text>Go to settng Tab</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Details')}>
<Text>Open Details Screen</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});

Related

View config getter callback for component 'H' must be a function (received undefined)

Error is:
Invariant Violation: View config getter callback for component 'H' must be a function (received undefined)
I'm using react-native to make application and error happens when I clicked login button in MainLogin.js file. (It has to move to mainpage when clicking login button in login page)
I searched a lot but cannot know what is component 'H'.
attatched index.js (src/screens/index.js) and MainLogin.js (src/screens/MainLogin.js)
<index.js>
import React from 'react';
import {
Text
} from 'react-native';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createBottomTabNavigator } from "react-navigation-tabs";
import LoginScreen from './MainLogin';
import HomeScreen from './MainPage';
import DiaryScreen from './Diarymemo';
import StatScreen from './MoodStatistics';
import CommuScreen from './Community';
import StoreScreen from './Store';
const HomeStack = createStackNavigator(
{
HomeScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Home'}),
}
);
const DiaryStack = createStackNavigator(
{
DiaryScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Diary'}),
}
);
const StatStack = createStackNavigator(
{
StatScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Stat'}),
}
);
const CommunityStack = createStackNavigator(
{
CommuScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Network'}),
}
);
const StoreStack = createStackNavigator(
{
StoreScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Store'}),
}
);
const TabNavigator = createBottomTabNavigator(
InitialRouteName = 'Home',
{
Diary: DiaryStack,
Stat: StatStack,
Home: HomeStack,
Network: CommunityStack,
Store: StoreStack,
},
{
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, horizontal, tintColor}) => {
const {routeName} = navigation.state;
let icon = "▲";
if(routeName === 'Diary'){
icon = "📓";
} else if(routeName === 'Stat'){
icon = "📊"
} else if(routeName === 'Home'){
icon = "🍎"
} else if(routeName === 'Network'){
icon = "👫"
} else if(routeName === 'Store'){
icon = "🛍"
}
// can use react-native-vector-icons
// <Icon name={iconName} size={iconSize} color={iconColor} />
return <Text style={{color: focused && "#46c3ad" || "#888"}}>{icon}</Text>
}
}),
lazy: false,
tabBarOptions: {
activeTintColor: "#46c3ad",
inactiveTintColor: "#888",
},
}
);
const AppStack = createStackNavigator(
{
LoginScreen: LoginScreen,
TabNavigator: {
screen: TabNavigator,
navigationOptions: ({navigation}) => ({
headerShown: false,
}),
},
}
);
export default createAppContainer(AppStack);
<MainLogin.js>
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet
} from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
export default class LoginScreen extends Component{
static navigationOptions = {
headerShown: false,
};
_doLogin(){
// do something
this.props.navigation.replace('TabNavigator')
}
render(){
return (
<View style={styles.container}>
<View style={styles.titleArea}>
<Text style={styles.title}>MoodiBuddy</Text>
</View>
<View style={styles.formArea}>
<TextInput
style={styles.textForm}
placeholder={"ID"}/>
<TextInput
style={styles.textForm}
placeholder={"Password"}/>
</View>
<View style={styles.buttonArea}>
<TouchableOpacity
style={styles.button}
onPress={this._doLogin.bind(this)}>
<Text style={styles.buttonTitle}>Login</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingLeft: wp('10%'),
paddingRight: wp('10%'),
justifyContent: 'center',
},
titleArea: {
width: '100%',
padding: wp('10%'),
alignItems: 'center',
},
title: {
fontSize: wp('10%'),
},
formArea: {
width: '100%',
paddingBottom: wp('10%'),
},
textForm: {
borderWidth: 0.5,
borderColor: '#888',
width: '100%',
height: hp('5%'),
paddingLeft: 5,
paddingRight: 5,
marginBottom: 5,
},
buttonArea: {
width: '100%',
height: hp('5%'),
},
button: {
backgroundColor: "#46c3ad",
width: "100%",
height: "100%",
justifyContent: 'center',
alignItems: 'center',
},
buttonTitle: {
color: 'white',
},
})

Add WebView via onClick in Expo React-Native

I need a function that creates new screens with a webview in it.
The main screen of my expo app contains a button "add new Page" which links to a page with a form to add domain, Username, Password.
if this is done, I want a list of pages in my main screen with all pages. for example if I click on "myWebsite1" with the generated link http://user:password#myWebsite1.com this page should be shown in a webview. same for website2, 3 and so on.
Anyone an idea how to do this?
EDIT: I add some code I have right now. For each Task I create, the Domain, User and Password for the webview file should change and be saved at this specific task. (and also open onclick). I turn in a circle
this is my app.js which expo opens first, it contains a Flatlist:
import React, { Component } from "react";
import { AppRegistry, StyleSheet, Text, View, FlatList, AsyncStorage, Button, TextInput, Keyboard, Platform, TouchableWithoutFeedback } from "react-native";
const isAndroid = Platform.OS == "android";
const viewPadding = 10;
const things = {things}
export default class NodeList extends Component {
state = {
tasks: [ ],
text: ""
};
changeTextHandler = text => {
this.setState({ text: text });
};
addTask = () => {
let notEmpty = this.state.text.trim().length > 0;
if (notEmpty) {
this.setState(
prevState => {
let { tasks, text } = prevState;
return {
tasks: tasks.concat({ key: tasks.length, text: text }),
text: ""
};
},
() => Tasks.save(this.state.tasks)
);
}
};
deleteTask = i => {
this.setState(
prevState => {
let tasks = prevState.tasks.slice();
tasks.splice(i, 1);
return { tasks: tasks };
},
() => Tasks.save(this.state.tasks)
);
};
componentDidMount() {
Keyboard.addListener(
isAndroid ? "keyboardDidShow" : "keyboardWillShow",
e => this.setState({ viewMargin: e.endCoordinates.height + viewPadding })
);
Keyboard.addListener(
isAndroid ? "keyboardDidHide" : "keyboardWillHide",
() => this.setState({ viewMargin: viewPadding })
);
Tasks.all(tasks => this.setState({ tasks: tasks || [] }));
}
render() {
return (
<View
style={[styles.container, { paddingBottom: this.state.viewMargin }]}
>
<Text style={styles.appTitle}>Nodes</Text>
<FlatList
style={styles.list}
data={this.state.tasks}
renderItem={({ item, index }) =>
<View>
<View style={styles.listItemCont}>
<TouchableWithoutFeedback onPress={() => Linking.openURL('')}>
<Text style={styles.listItem}>
{item.text}
</Text>
</TouchableWithoutFeedback>
<Button color= "#00BC8C" title="✖" onPress={() => this.deleteTask(index)} />
</View>
<View style={styles.hr} />
</View>}
/>
<TextInput
style={styles.textInput}
onChangeText={this.changeTextHandler}
onSubmitEditing={this.addTask}
value={this.state.text}
placeholder="+ add Node"
returnKeyType="done"
returnKeyLabel="done"
/>
</View>
);
}
}
let Tasks = {
convertToArrayOfObject(tasks, callback) {
return callback(
tasks ? tasks.split("||").map((task, i) => ({ key: i, text: task })) : []
);
},
convertToStringWithSeparators(tasks) {
return tasks.map(task => task.text).join("||");
},
all(callback) {
return AsyncStorage.getItem("TASKS", (err, tasks) =>
this.convertToArrayOfObject(tasks, callback)
);
},
save(tasks) {
AsyncStorage.setItem("TASKS", this.convertToStringWithSeparators(tasks));
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#252525",
padding: viewPadding,
paddingTop: 24
},
list: {
width: "100%"
},
listItem: {
paddingTop: 4,
paddingBottom: 2,
fontSize: 18,
color:"#ffff"
},
hr: {
height: 1,
backgroundColor: "gray"
},
listItemCont: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingTop: 10,
},
textInput: {
height: 40,
paddingRight: 10,
paddingLeft: 10,
borderColor: "gray",
borderWidth: isAndroid ? 0 : 1,
width: "100%",
color:"#ffff"
},
appTitle: {
alignItems:"center",
justifyContent: "center",
paddingBottom: 45,
marginTop: 50,
fontSize: 25,
color:"#ffff"
}
});
AppRegistry.registerComponent("NodeList", () => NOdeList);
and here is my second screen, which contains the component for the WebView:
import React, { Component, useState } from "react";
import { BackHandler } from 'react-native';
import { WebView } from 'react-native-webview';
var $ = require( "jquery" );
export default class nodeView extends Component {
constructor(props) {
super(props);
this.WEBVIEW_REF = React.createRef();
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = ()=>{
this.WEBVIEW_REF.current.goBack();
return true;
}
onNavigationStateChange(navState) {
this.setState({
canGoBack: navState.canGoBack
});
}
render(){
return (
<WebView
source={{ uri: `https://${user}:${password}#${domain}` }}
ref={this.WEBVIEW_REF}
style={{ marginTop: 20 }}
onNavigationStateChange={this.onNavigationStateChange.bind(this)}
/>
)
}
}
Create WebView. Create State Which Controls WebView. Add Listener To Button

React-Native Jitsi Meet 'null is not an object (evaluating 'JitsiMeetModule.call)' Error

I am new to react-native and Jitsi-Meet.
I a trying to develop a video-call app using Jitsi Meet.
I applied everything as in the descriptions on official website but I get the errors in the pics.
here are some of my codes
on my Jitsi.js component =
import React from 'react';
import { View } from 'react-native';
import JitsiMeet, { JitsiMeetView } from 'react-native-jitsi-meet';
class VideoCall extends React.Component {
constructor(props) {
super(props);
this.onConferenceTerminated = this.onConferenceTerminated.bind(this);
this.onConferenceJoined = this.onConferenceJoined.bind(this);
this.onConferenceWillJoin = this.onConferenceWillJoin.bind(this);
}
componentDidMount() {
console.log(props);
const { username, roomname } = this.props;
setTimeout(() => {
const url = `https://your.jitsi.server/${roomname}`; // can also be only room name and will connect to jitsi meet servers
const userInfo = {
displayName: `${username}`,
email: 'user#example.com',
avatar: 'https:/gravatar.com/avatar/abc123' };
JitsiMeet.call(url, userInfo);
/* You can also use JitsiMeet.audioCall(url) for audio only call */
/* You can programmatically end the call with JitsiMeet.endCall() */
}, 1000);
}
onConferenceTerminated(nativeEvent) {
/* Conference terminated event */
}
onConferenceJoined(nativeEvent) {
/* Conference joined event */
}
onConferenceWillJoin(nativeEvent) {
/* Conference will join event */
}
render() {
return (
<View style={{ backgroundColor: 'black',flex: 1 }}>
<JitsiMeetView onConferenceTerminated={this.onConferenceTerminated} onConferenceJoined={this.onConferenceJoined} onConferenceWillJoin={this.onConferenceWillJoin} style={{ flex: 1, height: '100%', width: '100%' }} />
</View>
);
}
}
export default VideoCall;
on my App.Js where I import jitsi component =
import React, {useState} from 'react';
import { Platform, StyleSheet, Text, View, Button, TextInput } from 'react-native';
import JitsiMeet from './components/jitsi'
const instructions = Platform.select({
ios: `Şu anda IOS konfigürasyon`,
android: `Android Konfigürasyon`,
});
export default function App() {
const [Count, setCount] = useState(0);
const [value, SetValue] = React.useState('');
const [value2, SetValue2] = React.useState('');
const addJitsi = () => {
try {
if (value !== '' && value2 !== '' ) {
const roomname = value.replace(/ |,|\.|/g, "");
const username = value2.replace(/ |,|\.|/g, "");
return <JitsiMeet roomname={roomname} username={username}/>
}
return <Text style={styles.welcome}>Lütfen alanları doldurunuz</Text>
} catch (error) {
console.log(error);
}
}
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.welcome}>Deep Lab University</Text>
<TextInput
style={styles.TextInputStyle}
onChangeText={text => SetValue(text)}
value={value}
placeholder='Kanal adı: '
/>
<TextInput
style={styles.TextInputStyle}
onChangeText={text => SetValue2(text)}
value={value2}
placeholder='Kullanıcı adı: '
/>
<Button title={'Kanal Oluştur'} style={{ marginBottom: '3%' }} onPress={(e) => console.log(value, value2)}/>
</View>
<Text style={styles.welcome}>Sayımız: `${Count}`</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
<Button title={`${Count}`} onPress={(e) => setCount(prevstate => prevstate +1)}/>
{
addJitsi()
}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
header: {
backgroundColor: '#999',
color: 'red',
minHeight: '50%',
width: '90%',
top: '1%',
marginTop: '0%',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
TextInputStyle: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
backgroundColor: 'white',
margin: '2%',
}
});
I can not go further . Thanks in advance

componentDidUpdate update logged just after click in screen

Im building a react native app and I faced a problem on componentDidUpdate.
When the app loads the componentDidMount call an api to check if the user are logged (using firebaseService.auth().onAuthStateChanged ), if it is, the app is redirected to main screen, otherwise to login screen. But the component just redirect to one of this screen when I click somewhere. Can someone help me?
Thanks
Follow my code:
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button, Image, FlatList,ActivityIndicator} from 'react-native';
import logo from '../../asserts/logo.png'
import { TouchableOpacity, TextInput } from 'react-native-gesture-handler';
import ListCard from '../../components/User/ListCard';
import { connect } from 'react-redux';
import axios from 'axios';
import { restoreSession} from '../../store/actions/Section/actions';
class Load extends Component {
componentDidMount(){
this.props.restore();
const { user, logged, error, loading } = this.props;
console.log("restore");
if(user && logged) this.props.navigation.navigate('User');
}
componentDidUpdate(prevProps) {
const { user, logged, error,loading } = this.props;
console.log("aqui");
if (!loading && !prevProps.error && error) Alert.alert('error', error);
if (!loading && logged) this.props.navigation.navigate('User');
}
constructor() {
super();
this.state = {
animating: false,
align: 'flex-start',
alignsecond: false,
};
setTimeout(
() =>
this.setState({ align: 'flex-start' }, function() {
this.setState({
alignsecond: true,
});
}),
100
);
}
render() {
return (
<View
style={{
flex: 1,
alignItems: 'center',
//flexDirection: 'row',
justifyContent: this.state.align,
marginTop : 150,
}}>
<Image
source={logo}
style={{ width: 200, height: 200 }}
/>
{!this.state.alignsecond ? null : (
<View style={{ margin: 10, justifyContent:'center',alignItems:'center' }}>
<Text
style={{ color: '#6F1121', fontSize: 30, fontWeight: 'bold' ,justifyContent:'center'}}>
HomeShare
</Text>
<Text
style={{ fontSize: 15,justifyContent:'center' }}>
Find a place to Share !
</Text>
<ActivityIndicator style={{ marginTop:20 }} size="large" color="gray" />
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
containerCard:{
flex:1,
flexDirection: 'column',
paddingTop:10 ,
paddingLeft:20,
paddingRight:20,
backgroundColor: 'rgba(220, 222, 211, 0.25)',
// marginTop: (Platform.OS === 'ios') ? 44 : StatusBar.currentHeight,
},
container:{
flex:1,
backgroundColor: 'rgba(220, 222, 211, 0.25)',
}
});
const mapStateToProps = ({ section: { restoring, loading, user, error, logged } }) => ({
restoring: restoring,
loading: loading,
user: user,
error: error,
logged: logged
});
const mapDispatchToProps = {
//login:loginUser,
restore:restoreSession
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Load);
My Action:
export const restoreSession = () => dispatch => {
dispatch(sessionLoading());
firebaseService.auth().onAuthStateChanged(async function(user) {
if (user) {
//console.log(user);
firebaseService.auth().currentUser.getIdToken(true).then(function(idToken) {
dispatch(sessionSuccess(idToken))
}).catch(function(error) {
dispatch(sessionError(e));
});
//dispatch(sessionSuccess(user));
} else {
dispatch(sessionLogout);
}
})
};
Personally, I would lose the logic for the componentDidMount and componentDidUpdate and just put the onAuthStateChange here in the componentDidMount so you can execute the navigate to the page.
Anyway, your problem is that the componentDidUpdate is executed when the page refreshes and that won't happen until you interact with it, and that is why it only analyzes the logged variable after you touch the screen. If you are thinking that the componentDidUpdate will execute every time you receive a new prop, that is wrong.
You should check this https://es.reactjs.org/docs/react-component.html#static-getderivedstatefromprops

How to re-render a tab in React-Native

I have a React-Native flashcard app that boots with two tabs, a Home tab, and a New Deck tab. The Home tab is the default, and you can press or swipe over to the New Deck tab.
The Home tab displays all of the decks the user currently has saved.
On the New Deck tab, I have the user enter the title of their new deck and press a submit button. When that submit button is pressed, I re-navigate to the Home tab.
My issue is: How in the world do I trigger a re-render on the Home tab from a button press on the New Deck tab so the user can see the deck they just created?
I know I could use Redux to solve this issue, but no other part of the app is optimized in a "Redux" fashion, and I'd really like to not redesign the architecture of my app for the sole purpose of updating a single screen, mostly because this is the only instance where I would need this ability.
I've attempted to get around this by passing screenProps containing the this.forceUpdate method all the way from the StackNavigator component, but it didn't work. I also tried manually update the state of the App component to trigger a re-render, but the re-render never happened (although the state did update).
App.js
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import AlphaHome from './Components/Home/AlphaHome'
import AlphaQuiz from './Components/Quiz/AlphaQuiz'
import AlphaNewUdaciDeck from './Components/NewUdaciDeck/AlphaNewUdaciDeck'
import AlphaNewUdaciCard from './Components/NewUdaciCard/AlphaNewUdaciCard'
import AlphaUdaciDeckDetails from './Components/UdaciDeckDetails/AlphaUdaciDeckDetails'
import { TabNavigator, StackNavigator } from 'react-navigation'
const Tabs = TabNavigator({
Home: {
screen: AlphaHome,
navigationOptions: {
tabBarLabel: 'Home',
},
},
NewDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
tabBarLabel: 'New Deck',
}
}
}, {
navigationOptions: {
header: null,
},
tabBarOptions: {
activeTintColor: 'white',
indicatorStyle: {
backgroundColor: 'white'
},
style: {
height: 50,
borderBottomColor: 'white',
backgroundColor: 'deepskyblue',
}
},
})
const Stack = StackNavigator({
Home: {
screen: Tabs,
},
AlphaNewUdaciDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaNewUdaciCard: {
screen: AlphaNewUdaciCard,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaUdaciDeckDetails: {
screen: AlphaUdaciDeckDetails,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
})
export default class App extends Component {
render() {
return (
<Stack />
)
}
}
Home.js
import React, { Component } from 'react'
import { ScrollView, View, Text, StyleSheet, AsyncStorage, ActivityIndicator } from 'react-native'
import UdaciDeck from '../Reusable/UdaciDeck'
import { getAllData } from '../../utils/AsyncApi'
export default class HomeExistingUser extends Component {
state = {
decks: null,
}
componentDidMount() {
let decks = getAllData()
setTimeout(() => {
this.setState({
decks
})
}, 1000)
}
showDetails = (title, count) => {
this.props.navigation.navigate('AlphaUdaciDeckDetails', {title, count})
}
render() {
const {decks} = this.state
return (
decks
? <ScrollView contentContainerStyle={styles.container}>
{decks.map(s => <UdaciDeck key={s[1].title} name={s[1].title} count={s[1].questions.length} method={this.showDetails} />)}
</ScrollView>
: <View style={[styles.container, {flex: 1, justifyContent: 'center'}]}>
<ActivityIndicator size='large' color='white' />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
minHeight: '100%',
backgroundColor: 'lightskyblue',
paddingTop: 20,
paddingBottom: 20,
alignItems: 'center',
},
})
NewDeck.js
import React, { Component } from 'react'
import { View, Text, TextInput, StyleSheet, AsyncStorage, TouchableNativeFeedback, Alert } from 'react-native'
import { addDeck } from '../../utils/AsyncApi'
// BUG: when adding a new deck (if HomeExistingUser is true) view doesn't update. Need to figure out a way to update on tab navigate back
export default class AlphaNewUdaciDeck extends Component {
state = {
input: '',
keys: null,
}
componentDidMount() {
AsyncStorage.getAllKeys()
.then(keys => this.setState({
keys
}))
}
handleSubmit = () => {
const {input, keys} = this.state
input.search(' ') > 0 || input.length < 1 || keys.filter(s => s === input).length > 0
? Alert.alert(`Please enter a valid name (${input.length < 1 || keys.filter(s => s === input).length > 0 ? `you can't save a deck with ${input.length < 1 ? 'no' : 'an already used'} name` : "no spaces"})`)
: addDeck(input)
;if(input.search(' ') < 0 || input.length > 0 || keys.filter(s => s === input).length < 1) {
this.props.navigation.goBack()
}
}
render() {
return (
<View style={[styles.container, styles.containerOne]}>
<View style={styles.containerTwo}>
<Text style={styles.text}>Name of the deck</Text>
<Text style={styles.text}>(Please no spaces)</Text>
<TextInput
autoFocus={true}
onChangeText={(input) => this.setState({
input
})}
selectionColor={'deepskyblue'}
underlineColorAndroid={'transparent'}
style={styles.input}
/>
<TouchableNativeFeedback onPress={this.handleSubmit}>
<View style={styles.btn}>
<Text style={styles.btnText}>Save Deck</Text>
</View>
</TouchableNativeFeedback>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'lightskyblue',
},
containerOne: {
alignItems: 'center',
},
containerTwo: {
marginTop: 50,
},
text: {
color: 'white',
fontSize: 20,
},
input: {
backgroundColor: 'white',
height: 50,
width: 300,
marginTop: 15,
fontSize: 20,
paddingLeft: 5,
paddingRight: 5,
color: 'deepskyblue'
},
btn: {
backgroundColor: 'deepskyblue',
marginTop: 50,
padding: 20,
paddingLeft: 50,
paddingRight: 50,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
},
btnText: {
color: 'white',
},
})
You should check out react-navigation-is-focused-hoc at https://github.com/pmachowski/react-navigation-is-focused-hoc to solve the specific problem you mentioned.
You can also try
onNavigationStateChange(prevState, newState)
there is a sample at How can I tell if the screen is navigated to with ReactNavigation

Categories

Resources