App doesnt detect state change but SigninScreen does - react-native

I am trying to implement Auth flow using useContext
When I click the button on SignInScreen the state inside that screen changes and rerenders itself, showing token string under a button. Unfortunatelly App is still showing Signin screen, it doesnt detect that the state has changed.
App.tsx:
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';
import SignUpScreen from './screens/SignUpScreen';
import SignInScreen from './screens/SignInScreen';
import { AuthProvider, useAuth } from './context/AuthContext';
const Stack = createNativeStackNavigator();
export default function App() {
const { token } = useAuth();
return (
<AuthProvider>
<SafeAreaProvider>
<NavigationContainer>
<Stack.Navigator>
{token === null ? (
<>
<Stack.Screen name="Signin" component={SignInScreen} />
<Stack.Screen name="Signup" component={SignUpScreen} />
</>
) : (
<>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
</AuthProvider>
);
}
AuthContext.tsx:
import * as React from 'react'
interface AuthState {
token: string | null
isLoading: boolean
publicAddress: string | null
}
type AuthAction = { type: 'SIGN_IN'; token: string } | { type: 'SIGN_OUT' }
type AuthPayload = string
interface AuthContextActions {
signIn: (data: AuthPayload) => void
signOut: () => void
}
interface AuthContextType extends AuthState, AuthContextActions {}
const AuthContext = React.createContext<AuthContextType>({
token: null,
isLoading: true,
publicAddress: null,
// eslint-disable-next-line #typescript-eslint/no-empty-function
signIn: () => {},
// eslint-disable-next-line #typescript-eslint/no-empty-function
signOut: () => {},
})
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [state, dispatch] = React.useReducer(AuthReducer, {
token: null,
isLoading: true,
publicAddress: null,
})
const authActions: AuthContextActions = React.useMemo(
() => ({
signIn: async (token: string) => {
dispatch({ type: 'SIGN_IN', token })
console.log(state)
//await setToken(token) //TODO:
},
signOut: async () => {
//await removeToken() // TODO: use Vars
dispatch({ type: 'SIGN_OUT' })
},
}),
[]
)
return (
<AuthContext.Provider value={{ ...state, ...authActions }}>
{children}
</AuthContext.Provider>
)
}
const AuthReducer = (prevState: AuthState, action: AuthAction): AuthState => {
switch (action.type) {
case 'SIGN_IN':
console.log(action.token)
return {
...prevState,
token: action.token, //TODO:
isLoading: false
}
case 'SIGN_OUT':
return {
...prevState,
isLoading: false,
token: null
}
}
}
export const useAuth = (): AuthContextType => {
const context = React.useContext(AuthContext)
if (!context) {
throw new Error('useAuth must be inside an AuthProvider with a value')
}
return context
}
SignInScreen.tsx:
import React from "react";
import {View, Text, Button} from 'react-native'
import { useAuth } from "../context/AuthContext";
export default function SignInScreen(){
const {signIn, token} = useAuth();
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Login with metamask" onPress={() => {
console.log('pressed')
signIn('token')
}}/>
<Text>{token}</Text>
</View>
);
}

Related

Conditional navigation inside Tabs

i want to show a screen depending on a state.
So when I click on the bottom left tab, if there is a valid user, I want to be redirected to the UserProfile-screen, else redirect to the LoginScreen.
The react-native navigation confuses me, i just cant see whats wrong.
So in LoginRoutes.tsx I just try to change this behaviour by using true / false
Thanks in Advance.
What I have so far:
BottomTabBar.tsx:
export const BottomTabNavigator = () => {
const colorScheme = useColorScheme();
return (
<Tab.Navigator
screenOptions={{
tabBarShowLabel: true,
tabBarStyle: {
backgroundColor: "#292929",
borderTopWidth:0
},
tabBarInactiveTintColor: "#919191",
tabBarInactiveBackgroundColor: "#292929",
tabBarActiveTintColor: Colors[colorScheme].text,
headerShown: false,
}}
>
<Tab.Screen
name="LoginRoutes"
component={LoginRoutes}
options={{ title: "Login", headerShown: false}}
/>
<Tab.Screen
name="SettingsTabScreen"
component={SettingsTabScreen}
options={{ headerShown: false,title:"test" }}
/>
</Tab.Navigator>
);
};
LoginRoutes.tsx
import * as React from "react";
import { ActivityIndicator, View, Text } from "react-native";
import AsyncStorage from "#react-native-async-storage/async-storage";
import { createStackNavigator } from "#react-navigation/stack";
import NavigationContainer from "./UserProfileStack";
import LoginScreen from "../Screens/LoginScreen";
import UserProfile from "../components/UserProfile";
import Colors from "../constants/Colors";
import { UserProfileInfo } from "../constants/Types";
function LoginRoutes({ navigation }: { navigation: any }) {
const [loading, setLoading] = React.useState(true);
const [user, setUser] = React.useState(null);
const Stack = createStackNavigator();
React.useEffect(() => {
// check if the user is logged in or not
AsyncStorage.getItem("user")
.then((userString) => {
if (userString) {
console.log("-----------EXISTING------------");
console.log(JSON.parse(userString).id);
setUser(JSON.parse(userString));
} else {
console.log("not logged in, showing LoginPage");
}
setLoading(false);
})
.catch((err) => {
console.log(err);
setLoading(false);
});
}, []);
if (loading) {
return (
<View
style={{
height: "100%",
justifyContent: "center",
backgroundColor: Colors.dark.background,
}}
>
<ActivityIndicator
size="large"
style={{ backgroundColor: Colors.dark.background }}
/>
<Text
style={{
color: Colors.dark.text,
marginTop: 10,
alignSelf: "center",
}}
>
retrieving userdata...
</Text>
</View>
);
}
return (
<NavigationContainer>
<Stack.Navigator>
{true ? (
<Stack.Screen name="LoginScreen" component={LoginScreen} />
) : (
<Stack.Screen name="UserProfile" component={UserProfile} />
)}
</Stack.Navigator>
</NavigationContainer>
);
}
export default LoginRoutes;
The stackNavigator:
import { createStackNavigator } from "react-navigation-stack";
import { createAppContainer } from "react-navigation";
import LoginScreen from "../Screens/LoginScreen";
import UserProfile from "../components/UserProfile";
import { UserProfileInfo } from "../constants/Types";
import { StackNavigationProp } from '#react-navigation/stack';
export type UserProfileStackParams = {
LoginScreen: undefined,
UserProfile: { profileInfo: UserProfileInfo };
};
const screens = {
LoginScreen: {
screen: LoginScreen,
navigationOptions: {headerShown: false,gestureEnabled:false},
},
UserProfile: {
screen: UserProfile,
navigationOptions: {headerShown: false,gestureEnabled:false},
},
};
// home stack navigator screens
const UserProfileStack = createStackNavigator(screens);
export default createAppContainer(UserProfileStack);
UserProfile.tsx
type Props = {
navigation: StackNavigationProp<UserProfileStackParams, "UserProfile">
loggedInUser: {}
};
const DATA = [
{
// contains valid data
},
];
export const UserProfile: React.FC<Props> = ({ navigation}) => {
const [steamID, setSteamID] = React.useState({ id: null, watchLists: null });
const [profileInfo, setProfileInfo] = React.useState<UserProfileInfo>(null);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
// check if the user is logged in or not
AsyncStorage.getItem("user")
.then((userString) => {
if (userString) {
console.log("logged in.");
setSteamID(JSON.parse(userString));
fetchUserProfile(steamID.id).then((response) => {
setProfileInfo(response);
});
} else {
console.log("not logged in, showing LoginPage");
}
setLoading(false);
})
.catch((err) => {
console.log(err);
setLoading(false);
});
}, []);
return (
<>
<Button
title="btn"
onPress={() => {
navigation.navigate("LoginScreen")
}}
></Button>
export default UserProfile;
Inside the BottomTabNavigator you can check if the user is logged in. You can get the user in the same way you're getting it in UserProfile.tsx file.
export const BottomTabNavigator = () => {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
// check for user
}, []);
return (
<Tab.Navigator
screenOptions={{ ... }}
>
<Tab.Screen
name="LoginRoutes"
component={user ? UserScreen : LoginScreen}
/>
</Tab.Navigator>
);
};
Alternatively, you can look into getting the user through Context Provider so that you don't have to check the storage every time you want to see if the user is logged in.
Read more about that here:
How To Manage User State with React Context
React Context

React Native pass parameters from Screen to Tab Navigator

I am trying to pass a parameter from a screen to the Tab Navigator. In this I want to use it. Following the corresponding lines from my App.tsx:
const Tab = createBottomTabNavigator();
const AppStack = () => {
const [chatcount, setChatcount] = React.useState(0);
...
chatbadge = (number) => {
setChatcount(number)
};
...
return(
<Tab.Navigator
initialRouteName="..."
tabBarOptions={{
activeTintColor: 'rgba(255,0,35, 1)',
inactiveTintColor: 'rgba(255,0,35, 0.7)',
inactiveBackgroundColor: 'rgb(255, 235, 238)',
activeBackgroundColor: 'rgb(255, 235, 238)',
style: {backgroundColor: 'rgb(255, 235, 238)'},
}}
>
...
<Tab.Screen name="Chats" component={() => <Chats chatbadge={this.chatbadge}/>}/>
...
</Tab.Navigator>
)
};
const App = () => {
return(
<ActionSheetProvider>
<AuthContext.Provider value={authContext} >
<NavigationContainer>
<AppStack/>
</NavigationContainer>
</AuthContext.Provider>
</ActionSheetProvider>
);
}
export default App;
Now I want to set the chatcount in my chats screen /Chats.tsx:
import * as React from "react";
import { Image, StyleSheet, View, Text, FlatList, TouchableOpacity, AsyncStorage, Platform, TextInput, SafeAreaView } from "react-native";
...
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
...
import Chat from "../screens/Chat";
...
const Stack = createStackNavigator();
function NavStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false}}>
<Stack.Screen name="Chats" component={Chats}/>
<Stack.Screen name="Chat" component={Chat}/>
...
</Stack.Navigator>
);
}
class Chats extends React.Component<{}, State> {
constructor(props) {
super(props);
this._isMounted = false;
}
state = {
data: [],
value: ""
}
componentDidMount() {
this._isMounted = true;
this._isMounted && this.fetchData()
this._isMounted && setInterval(() => this.fetchData(), 1000);
}
componentWillUnmount(){
this._isMounted = false;
}
fetchData = async () => {
if(this._isMounted){
const response = await fetch('...', {
....
});
const json = await response.json();
this.setState({data: json});
this.props.chatbadge(json)
}
}
...
render(){
...
const {navigation} = this.props
return(
<SafeAreaView style={styles.container}>
...
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
...
});
this.props.chatbadge(json) shows an error that this.props.chatbadge is not defined. console.log(this.props.chatbadge) displayes "undefined".
I would be very happy about help.
Best regards
Lukas

undefined is not an object (evaluating 'Context._context') - React Native

I am trying to wrap one of my navigators with User Context that I created. I have achieved this before in other projects but I am encountering an issue. I Tried following this solution but it doesn't seem to be the same issue I am encountering. I can't exactly tell what is wrong here.
App.js Code :
import React, { useContext, useEffect } from "react";
import { View, Text, AsyncStorage, Button } from "react-native";
import { createStackNavigator } from "#react-navigation/stack";
import HomeScreen from "./src/screens/HomeScreen";
import LoginScreen from "./src/screens/login";
import CalendarScreen from "./src/screens/Calendar";
import SignUpScreen from "./src/screens/signUp";
import { scale, vs } from "react-native-size-matters";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { createMaterialBottomTabNavigator } from "#react-navigation/material-bottom-tabs";
import { Icon } from "react-native-elements";
import UserContext, { UserProvider } from "./src/screens/Context/UserContext";
import { NavigationContainer } from "#react-navigation/native";
const Tab = createMaterialBottomTabNavigator();
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const signedIn = true; //this is for testing
const drawer_style = {
backgroundColor: "#202B35",
activeTintColor: "#000",
width: 200,
};
const drawer_item_style = {
activeTintColor: "orange",
inactiveTintColor: "#fff",
itemStyle: { marginVertical: vs(10) },
};
const non_user_stack = () => {
<Stack.Navigator>
<Stack.Screen
name="Sign in - Cal "
component={LoginScreen}
options={({ navigation }) => ({
headerShown: true,
headerTintColor: "orange",
headerStyle: {
backgroundColor: "#202B35",
},
})}
/>
<Stack.Screen
name="Sign up - Cal "
component={SignUpScreen}
options={({ navigation }) => ({
headerShown: true,
headerTintColor: "orange",
headerStyle: {
backgroundColor: "#202B35",
},
})}
/>
</Stack.Navigator>;
};
const UserMenu = () => {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Home"
drawerStyle={drawer_style}
drawerContentOptions={drawer_item_style}
drawerType="front"
>
<Drawer.Screen name="Home" component={MyStack} />
</Drawer.Navigator>
</NavigationContainer>
);
};
const MyStack = () => {
return(
<Stack.Navigator>
<Stack.Screen
name="Cal"
component={BottomNav}
options={({ navigation }) => ({
headerShown: true,
headerTintColor: "orange",
headerStyle: {
backgroundColor: "#202B35",
},
headerLeft: (props) => (
<Icon
size={25}
name={"ios-menu"}
iconStyle={{
fontSize: scale(30),
color: "orange",
margin: 5,
marginLeft: 10,
}}
type="ionicon"
color="orange"
onPress={() => {
navigation.toggleDrawer();
}}
/>
),
})}
/>
</Stack.Navigator>
)
};
export default App = () => {
const { isSignedIn, check_and_set_signin_status } = useContext(UserContext); //<-- causes crash
return (
isSignedIn === "false" ? (
<UserProvider>
<UserMenu />
</UserProvider>
) : (
<non_user_stack></non_user_stack>
);
);
};
UserContext.js :
import React, { useState, useEffect } from "react";
import * as Permissions from "expo-permissions";
import axios from "axios";
import { AsyncStorage } from "react-native";
//import registerForPushNotificationsAsync from "../Hooks/registerForPushNotifications";
import Constants from "expo-constants";
const UserContext = React.createContext();
const IS_SIGNEDIN = "is_signed_in";
export const UserProvider = ({ children }) => {
const [isSignedIn, setSignIn] = useState(null);
const [didAuthenticate, setAuthenticated] = useState(null);
//Check if this user already signed in before and didnt log out since their last session
//used for conditional rendering
const check_and_set_signin_status = async () => {
const signed_in = await AsyncStorage.getItem(IS_SIGNEDIN);
if (signed_in == null || signed_in == "false") {
await AsyncStorage.setItem(IS_SIGNEDIN, "false");
setSignIn("false");
} else {
setSignIn("true");
}
};
return (
<UserContext.Provider
value={{
isSignedIn, // well use this for conditional rendering
check_and_set_signin_status,
}}
>
{children}
</UserContext.Provider>
);
};
The Error :
there is some mistake in your code
you are not exporting UserContext but you are importing UserContext
in App.js file
you are trying to use useContext and provider in same file but you
have to useContext inside of Provider child component
you are non_user_stack with first letter capital but you have to
make first letter capital
UserContext.js : you have to export UserContext in this file
import React, { useState, useEffect } from "react";
import { Text } from 'react-native'
import * as Permissions from "expo-permissions";
import axios from "axios";
import { AsyncStorage } from "react-native";
//import registerForPushNotificationsAsync from "../Hooks/registerForPushNotifications";
import Constants from "expo-constants";
const UserContext = React.createContext();
export default UserContext;
const IS_SIGNEDIN = "is_signed_in";
export const UserProvider = ({ children }) => {
const [isSignedIn, setSignIn] = useState(null);
const [didAuthenticate, setAuthenticated] = useState(null);
const check_and_set_signin_status = async () => {
const signed_in = await AsyncStorage.getItem(IS_SIGNEDIN);
if (signed_in == null || signed_in == "false") {
await AsyncStorage.setItem(IS_SIGNEDIN, "false");
setSignIn("false");
} else {
setSignIn("true");
}
};
return (
<UserContext.Provider
value={{
isSignedIn, // well use this for conditional rendering
check_and_set_signin_status,
}}
>
{children}
</UserContext.Provider>
);
};
App.js Code :
const App = () => {
const { isSignedIn, check_and_set_signin_status } = useContext(UserContext); //<-- causes crash
console.log( isSignedIn, check_and_set_signin_status ,"useContext")
return isSignedIn === "false" ? (
<UserMenu />
) : (
<Non_user_stack></Non_user_stack>
);
};
const jsx = () => (
<UserProvider>
<App />
</UserProvider>
);
export default jsx;
In my case I imported badly
import ThemeContext from '../contexts/theme-context';
Instead
import { ThemeContext } from '../contexts/theme-context';
You should always check what you're exporting from your context folder
In my case I import { LocalContext } from ".././services/location/location.context";
instead of import { LocationContext } from ".././services/location/location.context";
Mine was:
I mistakenly imported the file (languageContext.js) instead of its function {LanguageContext} so now it goes like this where I called my context.
import {LanguageContext} from "../../Context/languageContext";
const { language } = useContext(languageContext);
i18n.locale = language;

Login component react-native

I am making a react-native application.
I am trying to find out how can I show or hide the login component on the basis of a token stored. If the token is present in the storage, it would skip the login screen to the dashboard.
Else it will show login screen.
Here is the code to the app.
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, AsyncStorage } from 'react-native';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
export default function App() {
var [ token, setToken ] = useState('');
function loginHandler(recievedToken) {
setToken(recievedToken);
}
async function _readData() {
try {
const value = await AsyncStorage.getItem('Token');
console.log(value);
if (value !== null) {
// We have data!!
loginHandler(value)
} else {
loginHandler(null);
}
} catch (error) {
// Error retrieving data
}
};
return (
<View>
<Login getToken={_readData()} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
You can put conditional statement in your code.
Try this code out.
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, AsyncStorage, ActivityIndictor } from 'react-native';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
export default function App() {
var [ token, setToken ] = useState('');
var [ loading, setLoading ] = useState(true);
function loginHandler(recievedToken) {
setToken(recievedToken);
setLoading(false);
}
async function _readData() {
try {
const value = await AsyncStorage.getItem('Token');
console.log(value);
if (value !== null) {
// We have data!!
loginHandler(value)
} else {
loginHandler(null);
}
} catch (error) {
// Error retrieving data
}
};
if( loading ) {
<ActivityIndictor/>
}
if(token == null){
return (
<View>
<Login getToken={_readData()} />
</View>
);
} else {
return (
<View>
<Dashboard />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Let me know if some error or correction.
Here AuthStack is Login Screen and BottomNavigation is DashBoard.
import React, { useEffect, useState } from "react";
import { NavigationContainer } from "#react-navigation/native";
import AuthStackScreen from "./routes/AuthStack";
import BottomNavigation from "./routes/BottomNavigator";
import firebase from "./config/firebase";
export default App = () => {
const [isLogin, setIsLogin] = useState(false);
const checkLoginIn = () => {
firebase.auth().onAuthStateChanged(user => {
if (user) {
setIsLogin(true);
} else {
setIsLogin(false);
}
});
};
useEffect(() => {
checkLoginIn();
}, []);
return (
<NavigationContainer>
{isLogin ? <BottomNavigation /> : <AuthStackScreen />}
</NavigationContainer>
);
};
In my case
I just used initialRouteName
import React, {Component} from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import AsyncStorage from '#react-native-async-storage/async-storage';
import Home from './components/Home';
import Login from './components/Login';
const Stack = createNativeStackNavigator();
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
routeName: 'Login',
};
}
async componentDidMount() {
const token = JSON.parse(await AsyncStorage.getItem('token'));
if (token !== null) {
this.setState({
routeName: 'Bluetooth',
});
}
SplashScreen.hide();
}
render() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName={this.state.routeName}
screenOptions={{
headerShown: false,
}}>
<>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Home" component={Home} />
</>
</Stack.Navigator>
</NavigationContainer>
);
}
}

this.props.navigation.navigate() is not an object

Why is this.props.navigation.navigate() not available in my component? In fact, this.props is completely empty? My setup is that App.js adds StartScreen.js and ListScreen.js to a stackNavigator. ListScreen.js is then used as a component in Startscreen.js and will serve as a stacknavigation...
ListScreen.js
import React, { Component } from "react";
import { ScrollView, View, Text, FlatList, ActivityIndicator } from "react-native";
import { List, ListItem } from 'react-native-elements';
import Styles from 'app/styles/Styles';
import Vars from 'app/vars/Vars';
class ListScreen extends Component {
/*
static navigationOptions = {
title: 'Välkommen',
headerStyle: Styles.header,
headerTintColor: Vars.colors.primary,
headerTitleStyle: Styles.headerTitle,
};
*/
constructor(props) {
super(props);
console.log(props);
this.state = {
loading: true,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false
};
}
componentDidMount() {
this.fetchItems();
}
fetchItems = () => {
const { page, seed } = this.state;
const url = 'http://appadmin.test/api/menu/'+this.props.id;
this.setState({ loading: true });
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: page === 1 ? res : [...this.state.data, ...res],
error: res.error || null,
loading: false,
refreshing: false
});
})
.catch(error => {
this.setState({ error, loading: false });
});
}
handleRefresh = () => {
console.log('several handleRefresh?');
this.setState(
{
page: 1,
seed: this.state.seed + 1,
refreshing: true
},
() => {
this.fetchItems();
}
);
};
handleLoadMore = () => {
console.log('several handleLoadMore?');
this.setState(
{
page: this.state.page + 1
},
() => {
this.fetchItems();
}
);
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
}}
>
<ActivityIndicator animating size="large" />
<Text style={Styles.textCenter}>
Laddar innehåll...
</Text>
</View>
);
};
renderListItem = ({ item }) => (
<ListItem
title = {item.title}
id = {item.id}
automaticallyAdjustContentInsets={false}
item = {item}
leftIcon={{
name: item.icon,
style: Styles.listitemIcon,
size: 36,
}}
onPress = {this.onItemPress}
style = { Styles.listItem }
titleStyle = { Styles.listitemTitle }
/>
)
onItemPress = (item) => {
this.props.navigation.navigate('List', {
id: item.id
});
}
render() {
return (
<ScrollView contentContainerStyle={Styles.listContainer}>
<FlatList
automaticallyAdjustContentInsets={false}
data = { this.state.data }
style={Styles.list}
keyExtractor={item => "key_"+item.id}
renderItem = { this.renderListItem }
ListFooterComponent={this.renderFooter}
onRefresh={this.handleRefresh}
refreshing={this.state.refreshing}
onEndReachedThreshold={50}
/>
</ScrollView>
);
}
}
export default ListScreen;
StartScreen.js
import React, { Component } from "react";
import {
View,
ScrollView,
Text,
StyleSheet,
Linking,
FlatList
} from "react-native";
import Styles from 'app/styles/Styles';
import Vars from 'app/vars/Vars';
import ListScreen from 'app/screens/ListScreen';
import { List, ListItem } from 'react-native-elements';
import Menu from './../../assets/data/navigation.json';
class StartScreen extends Component {
static navigationOptions = {
title: 'Välkommen',
headerStyle: Styles.header,
headerTintColor: Vars.colors.primary,
headerTitleStyle: Styles.headerTitle,
};
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false,
};
}
componentDidMount() {
this.fetchList();
}
fetchList = () => {
const { page, seed } = this.state;
const url = 'http://appadmin.test/api/menu/root';
this.setState({ loading: true });
fetch(url)
.then(response => {
return response.json();
})
.then(json => {
this.setState({
data: json,
error: null,
loading: false,
refreshing: false
});
})
.catch(error => {
this.setState({ error, loading: false });
});
}
render() {
return (
<ScrollView style={Styles.scrollContainer}>
<View style={Styles.hero}>
<Text style={[Styles.h1, Styles.whiteText]}>
Region Halland
</Text>
<Text style={[Styles.lead, Styles.whiteText]}>
Välkommen
</Text>
</View>
<ListScreen id=""/>
</ScrollView>
);
}
}
export default StartScreen;
App.js
import React from 'react';
import {
StyleSheet,
Text,
View,
Image,
} from 'react-native';
import initCache from "app/utilities/initCache";
import { AppLoading } from 'expo';
import {
createBottomTabNavigator,
createStackNavigator
} from 'react-navigation'
import StartScreen from 'app/screens/StartScreen';
import ListScreen from 'app/screens/ListScreen';
import AboutScreen from 'app/screens/AboutScreen';
import { icon } from 'app/components/Image.js';
import Ionicons from 'react-native-vector-icons/Ionicons'
const StartStack = createStackNavigator({
Start: {screen: StartScreen, tabBarLabel: 'Hem'},
List: {screen: ListScreen},
}, {
navigationOptions : {
headerTitle: <Image
source={ icon }
style={{ width: 30, height: 30 }} />,
tabBarLabel: 'hem'
}
});
const AboutStack = createStackNavigator({
About: AboutScreen,
});
const Tabs = createBottomTabNavigator({
StartStack: {screen: StartStack, navigationOptions: { title: 'Hem'}},
AboutStack: {screen: AboutStack, navigationOptions: { title: 'Om Region Halland'}}
}, {
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'AboutStack') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
} else if (routeName === 'StartStack') {
iconName = `ios-home${focused ? '' : '-outline'}`;
}
// You can return any component that you like here! We usually use an
// icon component from react-native-vector-icons
return <Ionicons name={iconName} size={24} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: '#0b457e',
inactiveTintColor: 'gray',
},
})
export default class App extends React.Component {
state = {
appIsReady: false,
};
componentWillMount() {
this._loadAssetsAsync();
}
async _loadAssetsAsync() {
try {
await initCache({
fonts: [
{'scala-sans-regular': require('./assets/fonts/ScalaSans-Regular.ttf')},
{'scala-sans-bold': require('./assets/fonts/ScalaSans-Bold.ttf')},
]
});
} catch (e) {
console.warn(
'There was an error caching assets (see: main.js), perhaps due to a ' +
'network timeout, so we skipped caching. Reload the app to try again.'
);
console.log(e.message);
} finally {
this.setState({ appIsReady: true });
}
}
render() {
if (this.state.appIsReady) {
return (
<Tabs />
);
} else {
return <AppLoading />;
}
}
}
const { navigate } = this.props.navigation;
then use it as : navigate(‘Signup’)}