Passing information from one screen to another (using function component) - react-native

Passing information from one screen (CategoriesScreen) to another (MealDetailScreen). Both Screens are function component. The error occurs when the onDateChange function is executed. The props.navigation.navigate... line is the issue.
From:
import React from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
import CalendarPicker from 'react-native-calendar-picker';
const CategoriesScreen = props => {
return (
<View style={styles.container}>
<CalendarPicker
onDateChange={onDateChange}
/>
</View>
);
};
const onDateChange = (onDateChange) => {
console.log(props);
props.navigation.navigate({
routeName: 'MealDetail',
params: { dateId: onDateChange }
});
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFFFFF',
marginTop: 10,
},
});
export default CategoriesScreen;
To:
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import { MEALS } from '../data/dummy-data';
import HeaderButton from '../components/HeaderButton';
const MealDetailScreen = props => {
const date = props.navigation.getParam('dateId');
return (
<Text> {date} </Text>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
export default MealDetailScreen;
Navigator:
import { Platform } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import CategoriesScreen from '../screens/CategoriesScreen';
import CategoryMealsScreen from '../screens/CategoryMealsScreen';
import MealDetailScreen from '../screens/MealDetailScreen';
import Colors from '../constants/Colors';
const MealsNavigator = createStackNavigator(
{
Categories: {
screen: CategoriesScreen
},
CategoryMeals: {
screen: CategoryMealsScreen
},
MealDetail: MealDetailScreen
},
{
// initialRouteName: 'Categories',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: Platform.OS === 'android' ? Colors.primaryColor : ''
},
headerTintColor:
Platform.OS === 'android' ? 'white' : Colors.primaryColor,
headerTitle: 'Quick Time'
}
}
);
export default createAppContainer(MealsNavigator);
When the onDateChange function gets executed, the following error appears:
Error Message

just do this put on onDateChange function inside scope of component
const CategoriesScreen = props => {
const onDateChange = (onDateChange) => {
console.log(props);
props.navigation.navigate({
routeName: 'MealDetail',
params: { dateId: onDateChange }
});
};
return (
<View style={styles.container}>
<CalendarPicker
onDateChange={onDateChange}
/>
</View>
);
};

Related

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.

React native, routing without a nav menu item

I have a drawer and bottom tab nav system on my app which works perfectly, but I"ve come to a point where I have modules where I want a button click to take the user to a page for data entry but I don't want that page on any nav bars, I just need to route to it on button press.
So in App.js i have my existing nav system:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View, Image } from 'react-native';
import Splash from './Splash';
import Login from './src/components/Login/Login';
import Dashboard from './src/components/Dashboard/Dashboard';
import Trends from './src/components/Trends/Trends';
import EnterWeight from './src/components/Dashboard/EnterWeight';
import Profile from './src/Profile';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import { createDrawerNavigator } from 'react-navigation-drawer';
import Icon from '#expo/vector-icons/Ionicons';
import * as SQLite from 'expo-sqlite';
const db = SQLite.openDatabase('testDatabase');
const DashboardTabNavigator = createMaterialBottomTabNavigator({
Dashboard: {screen:Dashboard},
Trends: {screen:Trends},
//Profile: {screen:Profile},
EnterWeight: {screen:EnterWeight}
},
{
barStyle: { backgroundColor: '#000'},
},
{
navigationOptions:({navigation})=>{
const {routeName} = navigation.state.routes[navigation.state.index]
return{
headerTitle:routeName
}
}
}
);
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
},
{
defaultNavigationOptions:({navigation}) => {
return {
headerLeft: (<Icon style={{paddingLeft:10}} onPress={()=>navigation.openDrawer()} name="md-menu" size={30} />),
headerRight: (<Image style={styles.crossLogo} source={require('./src/images/LOGO-cross_only.png')}/>)
}
}
});
const AppDrawerNavigator = createDrawerNavigator({
Dashboard:{screen:DashboardStackNavigator},
Logout:{screen:Login}
});
const AppSwitchNavigator = createSwitchNavigator({
Login:{screen: Login},
Dashboard:{screen:AppDrawerNavigator},
},
{
initialRouteName: 'Login',
});
export default class MMH_App_Final extends Component{
render() {
const App = createAppContainer(AppSwitchNavigator);
return(
<App />
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
crossLogo: {
width:30,
height:30,
marginRight:10
}
});
But on another page I have
<TouchableOpacity
style={styles.recordButton}
onPress={() => navigate('EnterWeight')}
>
I want to be able to navigate to EnterWeight without registering it in the navbar. How can I do that?
a simple way to do this is to manage order on your TabNavigator:
const DashboardTabNavigator = createMaterialBottomTabNavigator({
Dashboard: {screen:Dashboard},
Trends: {screen:Trends},
//Profile: {screen:Profile},
EnterWeight: {screen:EnterWeight}
},
{
barStyle: { backgroundColor: '#000'},
},
{
navigationOptions:({navigation})=>{
const {routeName} = navigation.state.routes[navigation.state.index]
return {
headerTitle: routeName,
order: [
'Dashboard',
'Trends',
//'Profile',
],
}
}
}
);
But you have other options like :
Create a custom TabNavigator
Reorder your stack implementation to
isolate this new screen

Splash screen should be initialized before rendering home screen

...
I am trying to remove Drawer Navigation and use bottom navigation instead, but I am not able to display the splash screen and then the home screen. Please help me as I am totally new to React Native
...
...
navigation code
...
import React from "react";
import { createStackNavigator, createAppContainer, createBottomTabNavigator } from "react-navigation";
import DoctorHome from "../containers/Home/DoctorHome/DoctorHome";
import Appointments from "../containers/DoctorFlow/Appointments/Appointments";
import EditProfile from "../containers/DoctorFlow/EditProfile/EditProfile";
import ViewClinic from "../containers/DoctorFlow/ViewClinic/ViewClinic";
import AddClinic from "../containers/DoctorFlow/AddClinic/AddClinic";
import Profile from "../containers/DoctorFlow/Profile/Profile";
import Proffession from "../containers/DoctorFlow/Profile/Proffession";
import {
View,
Image,
Touchable,
TouchableHighlight,
TouchableNativeFeedback,
Platform
} from "react-native";
const HomeStack = createStackNavigator ({
Home: DoctorHome,
Appointments: Appointments,
EditProfile: EditProfile
});
const ClinicStack = createStackNavigator ({
Clinic: ViewClinic,
AddClinic: AddClinic
});
const ProfileStack = createStackNavigator ({
Profile: Profile,
EditProfile: EditProfile,
Proffession: Proffession
});
const MainNavigator = createBottomTabNavigator({
Home: HomeStack,
Clinic: ClinicStack,
Profile: ProfileStack
});
export const AppNavigator = createAppContainer(MainNavigator);
...
splash screen code
...
import React, { Component } from "react";
import { AsyncStorage, Image, StyleSheet, Text, View } from "react-native";
import { connect } from "react-redux";
import TimerMixin from "react-timer-mixin";
import { StackActions, NavigationActions } from "react-navigation";
class Splash extends Component {
constructor(props) {
super(props);
this.state = {
user: null
};
}
componentWillMount() {}
componentDidMount() {
this.getUser();
TimerMixin.setTimeout(() => {
if (this.state.user) {
console.log(this.state.user.user.userType);
if (this.state.user.user.userType == "DOCTOR") {
if (this.state.user.user.isProfileCompleted == false) {
this.props.navigation.dispatch(
StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "EditDoctorProfile" })
]
})
);
} else {
this.props.navigation.dispatch(
StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "DoctorHomeMenu" })
]
})
);
}
}
} else {
this.props.navigation.dispatch(
StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Login" })]
})
);
}
}, 1000);
}
async getUser() {
await AsyncStorage.getItem("user").then(user =>
this.setState({ user: JSON.parse(user) })
);
}
render() {
return (
<View
style={{
justifyContent: "center",
alignItems: "center",
flex: 1,
backgroundColor: "#fff"
}}
>
<Image
style={{ width: 200, height: 40 }}
source={require("../Images/logo/logo.png")}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF",
padding: 16
},
welcome: {
fontSize: 20,
textAlign: "center",
margin: 10
},
instructions: {
textAlign: "center",
color: "#333333",
marginBottom: 5
}
});
const mapDispatchToProps = dispatch => ({
Login: () =>
dispatch(
NavigationActions.navigate({
routeName: "Login"
})
)
});
export default connect(
null,
mapDispatchToProps
)(Splash);
...
App.js (entry point)
...
import React from "react";
import { View, StatusBar } from "react-native";
import { Provider } from "react-redux";
import { AppNavigator } from "../Navigation/RootNavigation";
import configureStore from "../store/ConfigureStore";
import color from "../ui/color";
const store = configureStore();
export default class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View
style={{
flex: 1,
backgroundColor: color.primary
}}
>
<StatusBar
backgroundColor={"#000"}
barStyle="light-content"
hidden={false}
/>
<Provider store={store}>
<AppNavigator />
</Provider>
</View>
);
}
}
...
I want to display the logo first, and then I want a login/signup screen. Once the user logs in, he can access Home and inner screens.
But right now, I am directly getting Home screen as my opening screen. Please help me resolve this issue.
...
You'd probably want to make the login stack the default route:
const MainNavigator = createBottomTabNavigator({
Home: HomeStack,
Clinic: ClinicStack,
Profile: ProfileStack,
Login: LoginStack
}, {initialRouteName: 'Login'});
You probably also want to add the splash screen make it the default route
const LoginStack = createStackNavigator ({
Login: Login,
SignUp: SignUp,
Splash: Splash
}, {initialRouteName: 'Splash')

How to call mapStateToProps on each instance of a Component in React-Redux

I have a component called AuditionItem, multiple instances of which are added to the parent component called AuditionsList.
I have done export default connect(mapStateToProps)(AuditionItem)
From my experience mapStateToProps is called only for one instance of AuditionItem (the one that initiates the state change). But I want the mapStateToProps to be called for EACH instance of AuditionItem.
Is there a way to do this?
Here's my code for AuditionItem.js:
import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import Moment from 'moment';
import colors from './../styles/colors';
import { store } from './../App';
import { addBookmark, removeBookmark } from './../actions/creators';
import { connect } from 'react-redux';
class AuditionItem extends React.Component {
_toggleBookmark = (auditionId, bookmarked) => {
if(bookmarked)
store.dispatch(removeBookmark(auditionId));
else
store.dispatch(addBookmark(auditionId));
}
render() {
Moment.locale('en');
let bookmarked = (this.props.auditions.indexOf(this.props.auditionId) > -1) ? true : false;
let roleString = String(this.props.role);
if(roleString.length > 35)
roleString = roleString.substring(0, 35) + " ...";
let projectString = String("Project: (" + this.props.productionType + ") " + this.props.project);
if(projectString.length > 35)
projectString = projectString.substring(0, 35) + " ...";
let productionHouseString = String("Production House: " + this.props.productionHouse);
if(productionHouseString.length > 35)
productionHouseString = productionHouseString.substring(0, 35) + " ...";
let iconName = `ios-bookmark${bookmarked ? '' : '-outline'}`;
return (
<View style={styles.auditionItemWithBookmark}>
<View style={styles.bookmark}>
<TouchableOpacity onPress={() => this._toggleBookmark(this.props.auditionId, bookmarked)} >
<Ionicons name={iconName} size={25} />
</TouchableOpacity>
</View>
<View style={styles.auditionItem}>
<Text style={styles.role}>{roleString}</Text>
<Text style={styles.project}>{projectString}</Text>
<Text style={styles.productionHouse}>{productionHouseString}</Text>
<Text style={styles.auditionDate}>Begins: {Moment(String(this.props.auditionDate).replace('"','').replace('"', '')).format('LLLL')}</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
auditionItemWithBookmark: {
flex: 1,
flexDirection: "row",
backgroundColor: colors.auditionItemBackgroundColor,
borderRadius: 10,
margin: 10,
padding: 15,
},
bookmark: {
flex: 1,
paddingTop: 5,
},
auditionItem: {
flex: 8,
flexDirection: "column",
backgroundColor: colors.auditionItemBackgroundColor,
},
role: { color: colors.auditionItemColor, fontSize: 20, fontWeight: "bold" },
project: { color: colors.auditionItemColor },
productionHouse: { color: colors.auditionItemColor },
auditionDate: { color: colors.auditionItemColor },
});
const mapStateToProps = state => {
return {
auditons: state.bookmarks.auditions,
}
}
export default connect(mapStateToProps)(AuditionItem);
And the code for the parent AuditionsList.js
import React from 'react';
import { Text, View, FlatList, ActivityIndicator } from 'react-native';
import { connect } from 'react-redux';
import AuditionItem from './AuditionItem';
import Auditions from './../data/Auditions';
import { store } from './../App';
class AuditionsList extends React.Component {
constructor(props) {
super(props);
this.state = { isLoading: true, data: [] }
}
componentDidMount() {
this._refreshData();
}
componentDidUpdate(prevProps) {
if((this.props.location !== prevProps.location) || (this.props.roleType !== prevProps.roleType))
this._refreshData();
}
_onRefresh() {
this.setState({ isLoading: true }, this._refreshData() );
}
_refreshData = () => {
Auditions.fetchAuditions(this.props.productionType, this.props.location, this.props.roleType).then(auditions => {
this.setState({ isLoading: false, data: this._addKeysToAuditions(auditions) });
});
}
_addKeysToAuditions = auditions => {
return auditions.map(audition => {
return Object.assign(audition, { key: audition.Role});
});
}
_renderItem = ({ item }) => {
return (
<AuditionItem
auditionId={item.objectId}
role={item.Role}
project={item.Project.Name}
productionType={item.Project.ProductionType.Type}
auditionDate={JSON.stringify(item.Date.iso)}
productionHouse={item.Project.ProductionHouse.Name}
auditions={store.getState().bookmarks.auditions}
/>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={{ flex: 1 }}>
<FlatList onRefresh={() => this._onRefresh()} refreshing={this.state.isLoading} data={this.state.data} renderItem={this._renderItem} />
</View>
);
}
}
const mapStateToProps = state => {
return {
location: state.settings.location,
roleType: state.settings.roleType,
};
}
export default connect(mapStateToProps)(AuditionsList);
Code for App.js:
import React from 'react';
import { Text, View, ActivityIndicator } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { Header } from 'react-native-elements';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import { SettingsDividerShort, SettingsCategoryHeader, SettingsPicker} from 'react-native-settings-components';
import BookmarksScreen from './screens/BookmarksScreen';
import AuditionsScreen from './screens/AuditionsScreen';
import SettingsScreen from './screens/SettingsScreen';
import { AsyncStorage } from "react-native";
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import rootReducer from './reducers/index';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/lib/integration/react';
import { autoMergeLevel2 } from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
stateReconciler: autoMergeLevel2,
whitelist: ['settings', 'bookmarks']
};
const pReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(pReducer);
export const persistor = persistStore(store);
const MaterialBottomTabNavigator = createMaterialBottomTabNavigator(
{
Bookmarks: BookmarksScreen,
Auditions: AuditionsScreen,
Settings: SettingsScreen,
},
{
shifting: true,
initialRouteName: 'Auditions',
barStyle: { backgroundColor: 'black' },
}
);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<PersistGate loading={<ActivityIndicator />} persistor={persistor}>
<MaterialBottomTabNavigator />
</PersistGate>
</Provider>
)
}
}
This doesn't create an instance of the class, it just exports the class/object.
export default connect(mapStateToProps)(AuditionItem)
Export reference
You get the instance when you call the constructor of the class, but that's after importing it. So basically, all the time you use the imported AuditionItem (i.e: < AuditionItem />) React internally is creating a new instance of the class.
I guess the problem is either on AuditionItem itself, or the props you're passing to.
Additional information about mapStateToProps
from the official Redux documentation
[mapStateToProps(state, [ownProps]): stateProps] (Function): If this argument is specified, the new component will subscribe to Redux store updates. This means that any time the store is updated, mapStateToProps will be called. The results of mapStateToProps must be a plain object, which will be merged into the component’s props. If you don't want to subscribe to store updates, pass null or undefined in place of mapStateToProps.

react native navigation Could not find "store" in either the context or props of "Connect(facebookLogin)

I'm building react native app authentication with facebook login.
I'm using stack navigator and I want to add redux to my app.
I just seperate my files to components and when I use stack navigation with redux I get this error
Could not find "store" in either the context or props of
"Connect(facebookLogin)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(facebookLogin)".
index.android.js
import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, AppRegistry, Image } from 'react-native';
import facebookLogin from './src/components/FacebookLogin';
import Home from './src/components/Home';
import {
StackNavigator,
} from 'react-navigation';
const App = StackNavigator({
Home: { screen: facebookLogin },
HomePage: {screen:Home},
})
AppRegistry.registerComponent('facebookLogin', () => App);
FacebookLogin.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, AppRegistry, Image } from 'react-native';
import FBSDK, { LoginManager, GraphRequest, GraphRequestManager } from 'react-native-fbsdk';
import Icon from 'react-native-vector-icons/FontAwesome';
// redux
import { Provider } from 'react-redux';
import { connect } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../reducers/ProfileReducers';
const store = createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
class facebookLogin extends Component {
constructor(props) {
super(props);
this.state = {
result: null
}
}
_fbAuth() {
const { navigate } = this.props.navigation;
LoginManager.logInWithReadPermissions(['public_profile','user_birthday']).then((result) => {
if (result.isCancelled) {
console.log('Login was canclled');
}
else {
console.log(result);
const infoRequest = new GraphRequest(
'/me?fields=id,name,picture.width(800).height(800),gender,birthday,first_name,last_name',
null,
(error, result) => {
if (error) {
alert('Error fetching data: ' + error.toString());
} else {
console.log(result);
this.setState({ result });
navigate('HomePage');
}
}
);
// Start the graph request.
new GraphRequestManager().addRequest(infoRequest).start();
}
}, function (error) {
console.log('An error occured:' + error);
})
}
getProfileData() {
const { ImageStyle } = styles;
if (this.state.result) {
return (
<View>
{this.state.result.picture ? <Image style={ImageStyle} source={{ uri: this.state.result.picture.data.url }}></Image> : null}
<Text> first name: {this.state.result.first_name} </Text>
<Text> Last name: {this.state.result.last_name} </Text>
<Text> Gender {this.state.result.gender} </Text>
</View>
)
}
return null;
}
render() {
return (
<Provider store = {store}>
<View style={styles.container}>
<Icon.Button name="facebook" backgroundColor="#3b5998" onPress={() => { this._fbAuth() }}>
<Text style={{fontFamily: 'Arial', fontSize: 15, color:'white'}}>Login with Facebook</Text>
</Icon.Button>
{this.getProfileData()}
</View>
</Provider>
);
}
}
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,
},
ImageStyle:{
borderRadius:80,
width:100,
height:100
}
});
const mapStateToProps = (state) => {
return
{ profile: state.profile};
}
export default connect(mapStateToProps)(facebookLogin);
when it was only one component in index.android.js it works fine without any error but when I seperate it to some components using stack navigation I get this error.
my profileReducers
var profile = {
name :'',
email:'',
photo:''
}
const initialState = {
profile,
};
export default (state = initialState, action) => {
console.log("state");
switch (action.type) {
case 'INSERT_PROFILE_DETAILS':
return {
profile: action.payload
}
case 'GET_PROFILE_DETAILS': {
return state;
}
default:
return state;
}
}
Try setting up redux in index.android.js instead so it looks something like this:
// Set up redux store above
const Navigator = StackNavigator({
Home: { screen: facebookLogin },
HomePage: { screen: Home },
});
const App = () => (
<Provider store={store}>
<Navigator />
</Provider>
);
AppRegistry.registerComponent('facebookLogin', () => App);