How to hide splash screen in react native build using expo - react-native

My app is not loading after splash screen. It just stuck there.
So I added expo-splash-screen and still is not passing the splash screen. Before adding splash screen everything was working fine :(
See this is my App.js code. As you can see it only holds the navigation container which holds the links to other screens including the main home screen.
import {StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { MaterialIcons } from "#expo/vector-icons";
import { HomeNavigator } from './CustomNavigation';
import * as Font from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import FavouritesScreen from './src/screens/FavouritesScreen'
import HomeScreen from './src/screens/HomeScreen';
import MoreOptions from './src/screens/MoreOptions'
import React, { useEffect, useState } from 'react'
console.reportErrorsAsExceptions = false; //to hide touch warning
const Stack = createNativeStackNavigator()
const Tab = createBottomTabNavigator();
SplashScreen.preventAutoHideAsync();
export default function App() {
const [fontLoaded, setFontLoaded] = useState(false)
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
try {
await Font.loadAsync(Entypo.font);
await new Promise(resolve => setTimeout(resolve, 2000));
} catch (e) {
console.warn(e);
} finally {
// Tell the application to render
setAppIsReady(true);
}
}
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;` `
}
return (
<View
style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}
onLayout={onLayoutRootView}>
<StatusBar barStyle="dark-content" hidden={false} backgroundColor="#ff3b3b" translucent={true} />
<NavigationContainer>
//it contains nothing but the navigation code
</NavigationContainer>
</View>)
Please tell me where and what I'm doing wrong here.

I give you the working example please check it
then after you don't understand let me know
code
import React, { useRef, useEffect } from 'react';
import { StyleSheet, View, Image, StatusBar, Text } from 'react-native';
/**
* RN libraries
*/
import { useNavigation } from '#react-navigation/native';
export default function Splash() {
const animation = useRef(null);
const navigation = useNavigation();
useEffect(() => {
animation.current?.play();
navigation.addListener('focus', () => {
animation.current?.play();
});
setTimeout(() => {
navigate();
}, 2500);
}, []);
const navigate = () => {
navigation.navigate('Home');
};
return (
<View style={styles.animationContainer}>
<Text
style={{
textAlign: 'center',
fontSize: 50,
fontStyle: 'italic',
fontFamily: 'Poppins-Medium',
fontWeight: '800',
color: '#fff',
}}>
Online{'\n'}Education
</Text>
<Text
style={{ color: '#fff', fontSize: 20, fontFamily: 'Poppins-Medium' }}>
Free{'\n'}
</Text>
<View
style={{
backgroundColor: '#5D6CFA',
width: 169,
height: 117,
borderRadius: 60,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}}>
{/* <Text style={{color:"#000",fontFamily:'Poppins-Bold',fontSize:25}}>Let's start</Text> */}
</View>
</View>
);
}
const styles = StyleSheet.create({
animationContainer: {
backgroundColor: '#000',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
});

Maybe pass your setAppIsReady(true); after the finally and then remove it like this
React.useEffect(() => {
async function prepare() {
try {
// Pre-load fonts, make any API calls you need to do here
AsyncStorage.setItem("alreadyAppLaunched", "true")
await LoadFonts()
await checkOsDarkMode()
await stores.AuthStore.getAllData()
} catch (e) {
console.warn(e);
}
setReady(true);
}
prepare()
}, [])

Related

Splash screen rendering nothing instead of animation

I'm building a React Native application in expo, and am trying to use a gif file for a splash animation. I've configured my code as follows using expo-splash-screen, however nothing is rendered when I try to load the app. Any suggestions?
Here's the root of my app App.js
import 'react-native-gesture-handler';
import React, { useCallback,useState } from 'react'
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { MyStack } from './routes/homeStack';
import { useFonts } from 'expo-font';
import * as SplashScreen from 'expo-splash-screen'
import * as Sentry from 'sentry-expo';
import Splash from './components/Splash';
SplashScreen.preventAutoHideAsync();
export default function App() {
const [appIsReady, setAppIsReady] = useState(false);
const [ fontsLoaded ] = useFonts({
'Sofia-Pro': require('./assets/Sofia_Pro_Regular.otf'),
'Helvetica-Neue': require('./assets/HelveticaNeue-Medium.otf')
})
const onLayoutRootView = useCallback(async () => {
if (fontsLoaded) {
await SplashScreen.hideAsync();
}
}, [fontsLoaded]);
if (!fontsLoaded) {
return <Splash/>
}
return (
<NavigationContainer onLayout={onLayoutRootView}>
<MyStack/>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
And here's my splash animation component Splash.tsx
import React from 'react'
import { Image,StyleSheet,View } from 'react-native'
const Splash = () => {
return (
<View style = {styles.container}>
<Image
style = {styles.image}
source ={require('../assets/splash_animation.gif')}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
image: {
width: '100%',
height: '100%',
resizeMode: 'contain',
},
});
export default Splash

React native: can't configure the header with navigationOptions

I am new to react-native. I am trying to configure header styles for my app, but it's not working
App.js
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MealNavigator from './navigation/MealsNavigator';
export default function App() {
return (
<MealNavigator />
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
The following js file i am using for navigation
MealsNavigator.js
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from "react-navigation";
import categoriesScreen from '../screens/categoriesScreen';
import categoryMealScreen from '../screens/categoryMealScreen';
import mealDetailScreen from '../screens/mealDetailScreen';
const MealNavigator = createStackNavigator({
Categories : categoriesScreen,
CategoryMeals : categoryMealScreen,
MealDetail : mealDetailScreen
});
export default createAppContainer(MealNavigator);
The following is the screen where i am trying to configure the header
categoriesScreen.js
import React from 'react';
import {Text,View,Button,FlatList,StyleSheet,TouchableOpacity, Platform} from 'react-native';
import { CATEGORIES } from '../data/dummydata';
const CategoriesScreen = props => {
const renderGrid=(itemData) =>{
return(
<TouchableOpacity style={styles.gridItem} onPress={() =>{props.navigation.navigate({routeName:'CategoryMeals'});}}>
<View>
<Text>{itemData.item.title}</Text>
</View>
</TouchableOpacity>
)
};
return(
<View style={styles.container}>
<FlatList
data={CATEGORIES} renderItem={renderGrid} numColumns={2} />
</View>
);
}
CategoriesScreen.defaultNavigationOptions = ({ navigation }) =>({
title:'Meal Categories',
headerTitleStyle: {
textAlign: "left",
fontSize: 24
},
});
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems:'center'
},
gridItem:{
flexGrow:1,
padding: 20,
margin: 15,
height: 150,
}
});
export default CategoriesScreen;
The following is the dummy data i am using
dummydata.js
import Category from '../models/category';
export const CATEGORIES = [
new Category('c1','Indian','#f5428d'),
new Category('c2','Chinese','#f54242'),
new Category('c3','Thai','#f5a442'),
new Category('c4','Malaysian','#f5d142'),
new Category('c5','Arabian','#368dff'),
new Category('c6','South Indian','#41d95d'),
new Category('c7','Kerala','#9eecff'),
new Category('c8','Bengali','#b9ffb0'),
new Category('c9','Mexican','#ffc7ff'),
new Category('c10','Italian','#47fced'),
];
Following is category class file
category.js
class Category{
constructor(id,title,color){
this.id = id;
this.title = title;
this.color = color;
}
};
export default Category;
Everything else is working, just the header configuration is not working.I am using react navigation version 4
you can cofigure header using navigation.setOptions like this:
import React from 'react';
import {Text,View,Button,FlatList,StyleSheet,TouchableOpacity, Platform} from 'react-native';
import { CATEGORIES } from '../data/dummydata';
const CategoriesScreen = props => {
React.useLayoutEffect(() => {
props.navigation.setOptions({
headerTitle: 'Meal Categories',
headerTitleStyle: {
textAlign: "left",
fontSize: 24
},
});
},
const renderGrid=(itemData) =>{
return(
<TouchableOpacity style={styles.gridItem} onPress={() =>{props.navigation.navigate({routeName:'CategoryMeals'});}}>
<View>
<Text>{itemData.item.title}</Text>
</View>
</TouchableOpacity>
)
};
return(
<View style={styles.container}>
<FlatList
data={CATEGORIES} renderItem={renderGrid} numColumns={2} />
</View>
);
}
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems:'center'
},
gridItem:{
flexGrow:1,
padding: 20,
margin: 15,
height: 150,
}
});
export default CategoriesScreen;
I found a different solution to my problem. I used defaultNavigationOptions in my navigation file.
MealsNavigator.js
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from "react-navigation";
import categoriesScreen from '../screens/categoriesScreen';
import categoryMealScreen from '../screens/categoryMealScreen';
import mealDetailScreen from '../screens/mealDetailScreen';
import {Platform} from 'react-native';
import colors from '../constants/colors';
const MealNavigator = createStackNavigator({
Categories : {
screen : categoriesScreen,
navigationOptions : {
headerTitle:'Meal Categories',
}
},
CategoryMeals : {
screen : categoryMealScreen
},
MealDetail : mealDetailScreen
},
{
defaultNavigationOptions:{
headerTitleStyle:{
backgroundColor:Platform.OS==='android' ? colors.primaryColor : 'white'
},
headerTintColor:Platform.OS==='android' ? 'white' : colors.primaryColor
}
}
);
export default createAppContainer(MealNavigator);
Thanks to everybody for your help.

Force unmounting on screen change

I recently integrated React Redux and Redux Thunk into my application in the hope that it would better allow me to manage state across screens.
However, using my navigation library (react native router flux), when ever I navigate between screens I get warnings of trying to set state across unmounted components and I am not sure what I would even need to unmount in componentWillUnmount as no calls should happen after a screen navigation.
My question then is, how can I force unmount everything on componentWillUnmount? Is there something built into React Native that I should use? Or, in my navigation library?
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as Font from 'expo-font'
class CustomText extends Component {
async componentDidMount() {
await Font.loadAsync({
'varelaround-regular': require('../../../assets/fonts/varelaround-regular.ttf'),
'opensans-regular': require('../../../assets/fonts/opensans-regular.ttf'),
'opensans-bold': require('../../../assets/fonts/opensans-bold.ttf'),
});
this.setState({ fontLoaded: true });
}
state = {
fontLoaded: false,
};
setFontType = type => {
switch (type) {
case 'header':
return 'varelaround-regular';
case 'bold':
return 'opensans-bold';
default:
return 'opensans-regular';
}
};
render() {
const font = this.setFontType(this.props.type ? this.props.type : 'normal');
const style = [{ fontFamily: font }, this.props.style || {}];
const allProps = Object.assign({}, this.props, { style: style });
return (
<View>
{
this.state.fontLoaded ? (
<Text {...allProps}>{this.props.children}</Text>
) : <Text></Text>
}
</View>
);
}
}
export default CustomText;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
And one of my screens:
import React from "react";
import { ActivityIndicator, Image, StyleSheet, View } from "react-native";
import { Actions } from "react-native-router-flux";
import { connect } from "react-redux";
import * as profile from "../actions/profile";
import {
CustomText
} from "../components/common/";
class Home extends React.Component {
componentDidMount() {
this.props.loadProfile();
}
renderScreen() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 0.3 }}>
<CustomText type="header" style={styles.headerTextStyle} onPress={() => Actions.home()}>
Hello {this.props.name}!
</CustomText>
</View>
</View>
);
}
renderWaiting() {
return (
<GradientBackground type="purple">
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<ActivityIndicator size="large" color="#FFF" />
</View>
</GradientBackground>
);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.props.isLoading == true
? this.renderWaiting()
: this.renderScreen()}
</View>
);
}
}
function mapStateToProps(state) {
return {
name: state.profile.profile.friendly_name,
isLoading: state.profile.isLoading,
error: state.profile.error
};
}
function mapDispatchToProps(dispatch) {
return {
loadProfile: () => dispatch(profile.loadProfile())
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
const styles = StyleSheet.create({
headerTextStyle: {
color: "#FFFFFF",
fontSize: 40,
textAlign: "center",
marginVertical: 50
},
basicViewStyle: {
flex: 1
}
});

Unable to connect mapStateToProps and mapDispatchToProps

I'm getting an error that undefined is not a function(evaluating 'this.props.addTodo(text)')
my code was working fine before i introduces the react-navigation as after that i want to add a todo from my second screen i.e. Counter and want to see whether the list on screen one gets updated or not. but i got stuck at adding a todo on first screen as it is throwing the above error.
I'm a complete begginner in React-native and Redux and also in Js. Btw thanks and in advance
and here is my code:
App.js
import React from 'react';
import { StyleSheet, Text, View, AppRegistry } from 'react-native';
import TodoApp from './src/TodoApp'
import store from './app/store/index'
import { Provider } from 'react-redux'
import {CounterR} from './app/counterR';
import {Counter} from './app/counter';
import {createStackNavigator, createAppContainer} from 'react-
navigation'
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AppContainer />
</Provider>
);
}
}
const stack = createStackNavigator({
Home: CounterR,
Second: Counter
},{
initialRouteName: 'Home'
})
const AppContainer = createAppContainer(stack)
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
CounterR.js
import React, { Component } from 'react';
import {View,
TouchableOpacity,
Text,
Dimensions,
StyleSheet,
TextInput,
FlatList,
Keyboard} from 'react-native';
import {connect} from 'react-redux'
import { addTodo } from './actions/index'
import { toggleTodo } from './actions/index'
import {NavigationAction} from 'react-navigation'
import store from './store/index'
import { Provider } from 'react-redux'
const { width, height } = Dimensions.get("window");
export class CounterR extends Component{
state = {
text: ""
}
add = text => {
Keyboard.dismiss()
this.props.addTodo(text)
this.setState({text: ""})
}
render(){
return(
<View style={styles.container}>
<TextInput
style={{borderWidth:.5, width: 300, height: 40}}
defaultValue={this.state.text}
onChangeText={(value) => this.setState({text:value})}/>
<TouchableOpacity
onPress={() => this.add(this.state.text)}>
<Text
style={{fontSize: 18}}>ADD TODO</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Second')}>
<Text
style={{fontSize: 18}}>Second Screen</Text>
</TouchableOpacity>
<FlatList
data= {this.props.todos}
numColumns={1}
keyExtractor= {item => item.id}
renderItem ={({ item }) =>
<TouchableOpacity
onPress={() => this.props.toggleTodo(item)}
style={styles.todoText}>
<Text style={{textDecorationLine: item.completed ? 'line-through' : 'none', fontSize: 20}}>{item.text}</Text>
</TouchableOpacity>
}
/>
</View>
)
}
}
const mapStateToProps = state => ({
todos: state.todos
})
const mapDispatchToProps = dispatch => ({
addTodo: text => dispatch(addTodo(text)),
toggleTodo: item => dispatch(toggleTodo(item))
})
export default connect(mapStateToProps, mapDispatchToProps)(CounterR)
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
todoText: {
width: width,
margin: 10
}
});
Counter.js
import React, { Component } from 'react';
import {View,
TouchableOpacity,
Text,
Dimensions,
StyleSheet,
TextInput,
FlatList,
Keyboard} from 'react-native';
import {connect} from 'react-redux'
import { addTodo } from './actions/index'
import { toggleTodo } from './actions/index'
import { Provider } from 'react-redux'
import store from './store/index'
const { width, height } = Dimensions.get("window");
export class Counter extends Component{
state = {
text: "",
}
addTodo = text => {
Keyboard.dismiss()
this.props.addTodo(text)
this.setState({text: ""})
}
render(){
return(
<View style={styles.container}>
<TextInput
style={{borderWidth:.5, width: 300, height: 40}}
defaultValue={this.state.text}
onChangeText={(value) => this.setState({text: value})}/>
<TouchableOpacity
onPress={() => this.addTodo(this.state.text)}>
<Text
style={{fontSize: 18}}>ADD TODO</Text>
</TouchableOpacity>
</View>
)
}
}
const mapStateToProps = state => ({
todos: state.todos
})
const mapDispatchToProps = dispatch => ({
addTodo: text => dispatch(addTodo(text)),
toggleTodo: item => dispatch(toggleTodo(item))
})
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
todoText: {
width: width,
margin: 10
}
});
app/actions/index.js
import {Keyboard} from 'react-native'
import { ADD_TODO, TOGGLE_TODO } from './actionTypes'
let x = 0
export const addTodo = (text) => ({
type: ADD_TODO,
id: x++,
text: text
})
export const toggleTodo = (item) => ({
type: TOGGLE_TODO,
id: item.id
})
app/actions/actionTypes.js
export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
app/reducers/index.js
import { combineReducers } from 'redux'
import todos from './todos'
export default combineReducers({
todos
})
app/reducers/todos.js
const todos = (state =[], action) => {
switch(action.type){
case 'ADD_TODO':
return [
...state, {
id: action.id,
text: action.text,
completed: false
}
]
case 'TOGGLE_TODO':
return state.map(todo =>
(todo.id === action.id)
?
{...todo, completed: !todo.completed}
:
todo)
default:
return state
}
}
export default todos
app/store/index.js
import { createStore } from 'redux'
import rootReducer from '../reducers'
export default store = createStore(rootReducer)

React Native Auth with React Navigation and Redux

I have just started integrating Redux into my first React Native (Expo.io) project. I have got login working great with Redux, but when I try and create a logout button on one of the screens in my app, it actually triggers the log out dispatch as soon as it loads it. I think I must be misunderstanding the way Redux connect and mapDispatchToProps work. I have read the documentation many times but am still stuck. Here is the code in it's non-working state.
Log In - Works until I add the log out dispatch on profile page
import { connect } from "react-redux";
import React, { Component } from "react";
import {
Button,
View,
Text,
ActivityIndicator,
Alert,
FlatList
} from "react-native";
import { NavigationActions } from "react-navigation";
import { SocialIcon, Card } from "react-native-elements";
import Reactotron from "reactotron-react-native";
import { logIn } from "../actions";
import { signIn } from "../components/Auth";
class SignIn extends Component {
async handleClick() {
res = await signIn();
if (res != false) {
this.props.logIn(res.token);
} else {
console.log("Login Failed");
}
}
render() {
return (
<View style={{ paddingVertical: 20 }}>
<Card title="finis Requires A Facebook Account To Operate">
<SocialIcon
title="Fred"
button
type="facebook"
onPress={() => this.handleClick()}
/>
</Card>
</View>
);
}
}
const mapDispatchToProps = dispatch => {
return {
logIn: fbToken => {
dispatch(logIn(fbToken));
}
};
};
LoginScreen = connect(null, mapDispatchToProps)(SignIn);
export default LoginScreen;
Reducers
import { combineReducers } from "redux";
import Reactotron from "reactotron-react-native";
import { LOG_IN, LOG_OUT, ADD_PHONE_CONTACTS } from "../actions/actions";
const initialState = {
signedIn: false,
fbToken: "fred",
test: undefined,
phoneContacts: {}
};
const finis = combineReducers({
auth,
phoneContacts
});
function auth(state = initialState, action) {
switch (action.type) {
case LOG_IN:
Reactotron.log("LOG IN");
return {
...state,
signedIn: true,
fbToken: action.fbToken
};
case LOG_OUT:
Reactotron.log("LOG OUT");
return {
...state,
signedIn: false,
fbToken: undefined
};
default:
return state;
}
}
function phoneContacts(state = [], action) {
switch (action.type) {
case ADD_PHONE_CONTACTS:
console.log("Adding Contacts");
return {
...state,
phoneContacts: action.phoneContacts
};
default:
return state;
}
}
export default finis;
Profile Non working. Triggers LOG_OUT action without the button being pushed.
import React, { Component } from "react";
import { Button, Card } from "react-native-elements";
import { View, Text, ActivityIndicator, AsyncStorage } from "react-native";
import { MapView } from "expo";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { SimpleLineIcons } from "#expo/vector-icons";
import Reactotron from "reactotron-react-native";
import * as ActionCreators from "../actions";
import { signOut } from "../components/Auth";
class ProfileWrap extends Component {
handleClick() {
Reactotron.log(this.Actions);
this.props.logOut();
}
render() {
return (
<View style={{ paddingVertical: 20 }}>
<Card title="Profile">
<View
style={{
backgroundColor: "#bcbec1",
alignItems: "center",
justifyContent: "center",
width: 80,
height: 80,
borderRadius: 40,
alignSelf: "center",
marginBottom: 20
}}
>
<Text style={{ color: "white", fontSize: 28 }}>JD</Text>
</View>
<Button title="Log Out" onPress={this.handleClick} />
</Card>
</View>
);
}
}
mapDispatchToProps = dispatch => {
return {
logOut: dispatch(logOut())
};
};
const Profile = connect(null, mapDispatchToProps)(ProfileWrap);
export default Profile;
Any help would be appreciated, even if it's telling me I'm doing the whole thing wrong :) Been at this for hours.
NEW Profile.js - Gives Cannot read property 'logOut' of undefined
import React, { Component } from "react";
import { Button, Card } from "react-native-elements";
import { View, Text, ActivityIndicator, AsyncStorage } from "react-native";
import { MapView } from "expo";
import { connect } from "react-redux";
import { SimpleLineIcons } from "#expo/vector-icons";
import { logOut } from "../actions";
import { signOut } from "../components/Auth";
class ProfileWrap extends Component {
handleClick() {
console.log(this.props);
this.props.logOut();
}
render() {
return (
<View style={{ paddingVertical: 20 }}>
<Card title="Profile">
<View
style={{
backgroundColor: "#bcbec1",
alignItems: "center",
justifyContent: "center",
width: 80,
height: 80,
borderRadius: 40,
alignSelf: "center",
marginBottom: 20
}}
>
<Text style={{ color: "white", fontSize: 28 }}>JD</Text>
</View>
<Button title="Log Out" onPress={this.handleClick} />
</Card>
</View>
);
}
}
const mapDispatchToProps = dispatch => {
return {
logOut: function() {
dispatch(logOut());
}
};
};
const Profile = connect(null, mapDispatchToProps)(ProfileWrap);
export default Profile;
Your mapDispatchToProps should be returning an object with functions. The way you have it now, logOut() will be called immediately since it's not inside a function. Changing it to this should fix it:
const mapDispatchToProps = dispatch => {
return {
logOut: function () {
dispatch(logOut());
}
};
};
Here's a slightly cleaner way of doing it:
const mapDispatchToProps = dispatch => ({
logOut() {
dispatch(logOut());
}
});
Also, you're missing const in front of mapDispatchToProps but that shouldn't have affected anything.
Edit:
You don't have to use this now, but it'll be helpful in the future - if your component is only using the render method you can change it to a stateless functional component. It's currently the recommended way of creating components when possible:
const ProfileWrap = props => (
<View style={{ paddingVertical: 20 }}>
<Card title="Profile">
<View
style={{
backgroundColor: "#bcbec1",
alignItems: "center",
justifyContent: "center",
width: 80,
height: 80,
borderRadius: 40,
alignSelf: "center",
marginBottom: 20
}}
>
<Text style={{ color: "white", fontSize: 28 }}>JD</Text>
</View>
<Button title="Log Out" onPress={props.logOut} />
</Card>
</View>
);