I developing application for android-tv I need set focus in TouchableOpacity.
How can i do this?
My example of focus detection on Android TV
enableTVEventHandler() {
this.evtHandler = new TVEventHandler();
this.evtHandler.enable(this, this.handleTVRemoteEvent);
}
disableTVEventHandler() {
if (this.evtHandler) {
this.evtHandler.disable();
delete this.evtHandler;
}
}
handleTVRemoteEvent = (cmp, event) => {
const { eventType, tag } = event;
if (tag !== this.nodeHandle) {
return;
}
if (eventType === "focus") {
this.setState({ isFocus: true });
if (this.props.focus !== undefined) {
this.props.focus();
}
}
if (eventType === "blur") {
this.setState({ isFocus: false });
}
}
After working for a while i found this solution:
<TouchableHighlight
onPress={this.props.onPress}
onFocus={() => {
this.setState({
currentStyle: 'blue',
})
}}
onBlur={() => {
this.setState({
currentStyle: 'white',
})
}}
>
{this.props.children}
</TouchableHighlight>
Related
I am not able to get an alert when the api response fails.I am trying to add the alert in where the actions are getting dispatched.Can we trigger an alert of we have redirect to a different page after the submission? Is there any other way to show the error msg when the api response fails.
const saveOPPInfo = () => {
this.setState({
_firstNameEmpty: isEmpty(_firstName),
_lastNameEmpty: isEmpty(_lastName),
_emailNotValid: !validateEmail(_email)
});
if (
this.isSaveAttempted ||
isEmpty(_firstName) ||
isEmpty(_lastName) ||
!validateEmail(_email)
) {
return;
}
this.isSaveAttempted = true;
this.setState({ _isFetching: true });
if (action === "ADD") {
const jsonPayload = [
{
email: _email,
firstName: _firstName,
lastName: _lastName,
isPrimary: false
}
];
addOtherPickupPerson({ purchaseContractId, jsonPayload }).then(() => {
GroceryNotifierApi.events().emitOnAction("saveOPPInfo", "");
});
} else {
const jsonPayload = {
email: _email,
firstName: _firstName,
lastName: _lastName,
isPrimary: false
};
editOtherPickupPerson({ purchaseContractId, jsonPayload, pickupPersonId: _id }).then(() => {
GroceryNotifierApi.events().emitOnAction("saveOPPInfo", "");
});
}
};
here is the part of jsx
<View
style={{
paddingLeft: 20,
paddingRight: 20,
paddingTop: 24
}}
>
{action === "ADD" ? (
<Body>
{OPP_ADD_OPP_DESC}
<Body
onPress={() => nativeNav.navigateToOPPLearnMore()}
style={{ textDecorationLine: "underline" }}
>
{OPP_LEARN_MORE}
</Body>
</Body>
) : (
<View />
)}
</View>
{_isFetching && (
<View style={{ height: 120 }}>
<CircularIndicator />
</View>
)}
<View style={styles.bottom}>
<PrimaryButton
style={styles.saveButton}
testID="save"
block
onPress={saveOPPInfo}
disabled={this.isSaveAttempted || _firstNameEmpty || _lastNameEmpty || _emailNotValid}
>
{isIOS ? "Save" : "SAVE"}
</PrimaryButton>
{action === "ADD" ? (
<View />
) : (
<LinkButton onPress={removeOPPInfo} disabled={this.isSaveAttempted}>
{OPP_REMOVE}
</LinkButton>
)}
</View>
</View>
);
}
this is how the action looks
export const addOtherPickupPersonRequest = createAction(ADD_OTHER_PICKUP_PERSON_REQUEST);
export const addOtherPickupPersonSuccess = createAction(ADD_OTHER_PICKUP_PERSON_SUCCESS);
export const addOtherPickupPersonFail = createAction(ADD_OTHER_PICKUP_PERSON_FAIL);
export const addOtherPickupPerson = ({ purchaseContractId, jsonPayload }) => {
return async function(dispatch) {
store.dispatch(addOtherPickupPersonRequest());
let response;
let responseJson;
try {
const startTime = new Date().getTime();
response = await fetchAddOtherPickupPerson(purchaseContractId, jsonPayload);
if (response.status >= 200 && response.status < 300) {
trackPerformance("checkout-add-opp-api", startTime, "performance-metric");
responseJson = await response.json();
store.dispatch(addOtherPickupPersonSuccess(responseJson));
return responseJson;
} else {
Alert.alert(
"Oops22!",
"Something is not working here. Please check back later.",
[{ text: "Okay" }],
{ cancelable: false }
);
await Promise.reject(err);
}
} catch (err) {
trackErrorEvent("checkout-add-opp-api", { ...defaultPayload({ err }) }, "api-error");
Alert.alert(
"Oops!",
"Something is not working here. Please check back later.",
[{ text: "Okay" }],
{ cancelable: false }
);
return store.dispatch(addOtherPickupPersonFail(err));
}
};
};
I want to show an alert when the response.status is not response.status >= 200 && response.status < 300)
I had been developing my app for Web, and it has been working properly. However, when I ran the same app within Expo / Android, I got this error. Hard to know what it is about from the description.
This is the full error message:
Cannot add a child that doesn't have a YogaNode to a parent without a measure function! (Trying to add a '[RCTVirtualText 507]' to a '[RCTView 509]')
Do you know what it could possibly be?
This seems to be the js file that is triggering it:
...
export class SubjectListAssignScreen extends React.Component {
state = {
subjectList: [],
subListLoading: true,
};
constructor(props) {
super(props);
};
scrollDimensions = [{
width: Math.round(Dimensions.get('window').width - 20),
maxHeight: Math.round(Dimensions.get('window').height - 200)
}];
...
_getSubjects = async(text) => {
try {
await this.setState({ subListLoading: true });
let lQueryRes = await API.graphql(graphqlOperation(cqueries.listSubjectsCustom, {}));
await console.log('==> Subjects Query');
await console.log(lQueryRes);
await this.setState({ subjectList: lQueryRes.data.listSubjects.items });
await this.setState({ subListLoading: false });
}
catch (e) {
console.log("==> DB Error");
console.log(e);
await this.setState({ subListLoading: false });
};
};
...
_subjectItems = (value) => {
console.log(value.desc);
let lnum = (typeof value["num"] !== 'undefined') ? value["num"].toString() : null;
let desc = value["desc"].toString();
let lastName = (typeof value["users"][0] !== 'undefined') ? value["users"][0]["lastname"].toString() : null;
let ltype = value["type"].toString();
return (
<DataTable.Row onPress={() => {
this.props.navigation.navigate("UserListScreen", {pnum: lnum, ptype: ltype});
}}>
<DataTable.Cell>
{this._getTypeIcon(ltype)}
</DataTable.Cell>
<DataTable.Cell>
<Text>{desc}</Text>
</DataTable.Cell>
<DataTable.Cell>
<Text>{ lastName }</Text>
</DataTable.Cell>
</DataTable.Row>
);
};
async componentDidMount() {
try {
await this._getSubjects();
}
catch (e) {
console.log("==> componentDidMount error");
console.log(e);
};
};
isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
fetchMore = () => {
};
render() {
let sDimensions = this.scrollDimensions;
return (
<View style={{flex:20, margin:4, flexDirection:"column", justifyContent:"flex-start"}}>
<Title style={{flex:1}}>Lista de Demandas</Title>
<SafeAreaView style={[{flex:19, }, sDimensions]}>
<ScrollView
contentContainerStyle={{}}
onScroll={({nativeEvent}) => {
if (this.isCloseToBottom(nativeEvent)) {
this.fetchMore();
}}}
>
<DataTable>
<DataTable.Header>
<DataTable.Title>Type</DataTable.Title>
<DataTable.Title>Subj</DataTable.Title>
<DataTable.Title>Resp.</DataTable.Title>
</DataTable.Header>
{ !this.state.subListLoading ?
<FlatList
data={this.state.subjectList}
renderItem={({item})=>this._subjectItems(item)}
keyExtractor={item => item.desc}
/>
:
<ActivityIndicator />
}
</DataTable>
</ScrollView>
</SafeAreaView>
</View>
)
}
}
Using Expo 37, React Native paper and AWS Amplify.
As I had such a hard time trying to find which components were not compatible, I simply dropped my full development environment, create a clean one and pulled the latest commit again, checking all components version by version and making sure all of them were at the -g version. The error has stopped after that.
I have added a floating icon from react-native-floating-action package. I need to apply the different position for different pages, how to apply, this is my code. Its not working.
floatingIconEdge = () => {
// floating icon showing edges for different screens
const { currentScreen } = this.state
switch (currentScreen) {
case 'ShopScreen':
return { vertical: 40, horizontal: 10 }
case 'StoreHome':
return { vertical: 10, horizontal: 10 }
default:
return { vertical: 40, horizontal: 40 }
}
}<FloatingAction
actions={actions}
floatingIcon={<Icon name={'ios-help-circle-outline'} style={{ fontSize: 30, color: '#ffffff' }} />}
onPressItem={name => {
Reactotron.error({ name });
NavigationService.navigate('ChatRoom')
}}
distanceToEdge={this.floatingIconEdge()}
color={'#2cb673'}
visible={this.floatingIconVisible()}
/>
You can make a class for the floating button and then you can modify it for each screen like you want using props.
Here is an exemple: https://snack.expo.io/BJLGJl36r
class App extends Component {
constructor(props) {
super(props);
OneSignal.init('xxxxxxxxxxxxxxxxxxxxx');
OneSignal.setSubscription(true);
OneSignal.addEventListener('received', this.onReceived);
OneSignal.addEventListener('opened', this.onOpened);
OneSignal.addEventListener('ids', this.onIds);
OneSignal.getPermissionSubscriptionState((status) => {
console.log(status);
Reactotron.error({ oneSignalErrStatus: status });
});
AsyncStorage.setItem('CameraChoice', '0');
this.state = {
currentScreen: '',
distanceToEdge: { vertical: 40, horizontal: 10 }
};
}
componentWillUnmount() {
OneSignal.removeEventListener('received', this.onReceived);
OneSignal.removeEventListener('opened', this.onOpened);
OneSignal.removeEventListener('ids', this.onIds);
}
componentDidMount() {
// TODO set this.state.currentScreen
Reactotron.log('didMount>>>>>');
this.floatingIconEdge()
}
onReceived = (notification) => {
console.log('Notification received: ', notification);
Reactotron.error({ log: 'notification', place: 'inside onReceived', notification });
};
onOpened = (openResult) => {
console.log('Message: ', openResult.notification.payload.body);
Reactotron.error({ log: 'notification', place: 'inside onOpenend', notification: openResult.notification });
console.log('Data: ', openResult.notification.payload.additionalData);
console.log('isActive: ', openResult.notification.isAppInFocus);
console.log('openResult: ', openResult);
};
onIds = (device) => {
Reactotron.error({ log: 'notification', place: 'inside onIds', notification: device });
console.log('Device info: ', device);
};
// gets the current screen from navigation state
getActiveRouteName = (navigationState) => {
if (!navigationState) {
return null;
}
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return this.getActiveRouteName(route);
}
return route.routeName;
};
floatingIconVisible = () => {
// floating icon showing or not if user is logged in or not.
const { currentScreen } = this.state
if (checkLoggedIn()) {
if (currentScreen == 'ChatRoom') {
return false
}
else {
return true
}
} else {
return false
}
// switch (currentScreen) {
// case 'PhoneSignup':
// return false;
// case 'WelcomeReorder':
// return false;
// case 'CreateAccount':
// return false;
// case 'NumberVerification':
// return false;
// case 'ChatRoom':
// return false;
// case 'ReceiptScreen':
// return false;
// case 'MainCamera':
// return false;
// case 'VendingCamera':
// return false;
// default:
// return true;
}
floatingIconEdge = () => {
// floating icon showing edges for different screens
const { currentScreen } = this.state
Reactotron.log({ currentScreen1111: currentScreen });
switch (currentScreen) {
case 'ShopScreen':
this.setState({ distanceToEdge: { vertical: 0, horizontal: 0 } })
case 'StoreHome':
this.setState({ distanceToEdge: { vertical: 0, horizontal: 0 } })
default:
this.setState({ distanceToEdge: { vertical: 40, horizontal: 40 } })
}
// if (currentScreen == 'ShopScreen') {
// Reactotron.log({ if: 'if' });
// return { vertical: 500, horizontal: 40 }
// }
// else {
// Reactotron.log({ else: 'else' });
// // return { horizontal: 10, vertical: 10 }
// }
}
/**
* Render method
*
* #return {component}
*/
render() {
const { store, persistor } = getStore();
const actions = [
{
text: 'Start Chat',
icon: <Icon name={'ios-chatboxes'} style={{ fontSize: 20, color: '#ffffff' }} />,
name: 'chat',
position: 2,
color: '#2cb673'
},
{
text: 'Ping Retailer',
icon: <Icon name={'ios-hand'} style={{ fontSize: 20, color: '#ffffff' }} />,
name: 'ping',
position: 1,
color: '#2cb673'
}
// {
// text: "Location",
// icon: require("./images/ic_room_white.png"),
// name: "bt_room",
// position: 3
// },
// {
// text: "Video",
// icon: require("./images/ic_videocam_white.png"),
// name: "bt_videocam",
// position: 4
// }
];
return (
<ApolloProvider client={appSyncClient}>
<Provider store={store}>
<View style={{ flex: 1 }}>
{/* <PersistGate loading={null} persistor={persistor}> */}
{/* <Router
onNavigationStateChange={(prevState, currentState) => {
const currentScreen = this.getActiveRouteName(currentState);
this.setState({currentScreen});
// const prevScreen = this.getActiveRouteName(prevState);
// if (prevScreen !== currentScreen) {
// // the line below uses the Google Analytics tracker
// // change the tracker here to use other Mobile analytics SDK.
// Reactotron.error({log:'NAVIGATION STATE CHANGE', prevScreen, currentScreen});
// }
}}
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/> */}
<AppContainer
onNavigationStateChange={(prevState, currentState, action) => {
const currentScreen = this.getActiveRouteName(currentState);
this.setState({ currentScreen });
firebase.analytics().setCurrentScreen(currentScreen);
store.dispatch(setCurrentScreen({ name: currentScreen }));
if (
action.type === 'Navigation/NAVIGATE' ||
action.type === 'Navigation/DRAWER_CLOSED' ||
action.type === 'Navigation/RESET' ||
(action.type === 'Navigation/MARK_DRAWER_SETTLING' && !action.willShow)
) {
if (store.getState().currentScreen.isDrawerOpen) {
StatusBar.setHidden(false);
store.dispatch(setDrawerStatus(false));
}
} else if (
action.type === 'Navigation/DRAWER_OPENED' ||
action.type === 'Navigation/MARK_DRAWER_ACTIVE' ||
(action.type === 'Navigation/MARK_DRAWER_SETTLING' && action.willShow)
) {
if (!store.getState().currentScreen.isDrawerOpen) {
// StatusBar.setHidden(true);
store.dispatch(setDrawerStatus(true));
}
}
// const prevScreen = this.getActiveRouteName(prevState);
// if (prevScreen !== currentScreen) {
// // the line below uses the Google Analytics tracker
// // change the tracker here to use other Mobile analytics SDK.
// Reactotron.error({log:'NAVIGATION STATE CHANGE', prevScreen, currentScreen});
// }
}}
ref={(navigatorRef) => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
{/* </PersistGate> */}
<LoginModal navigation={NavigationService} />
<CategoryTransaction />
{ /* Floating Icon */}
<FloatingAction
actions={actions}
floatingIcon={<Icon name={'ios-help-circle-outline'} style={{ fontSize: 30, color: '#ffffff' }} />}
onPressItem={name => {
Reactotron.error({ name });
NavigationService.navigate('ChatRoom')
}}
distanceToEdge={this.state.distanceToEdge}
// distanceToEdge={{ vertical: 40, horizontal: 40 }}
color={'#2cb673'}
visible={this.floatingIconVisible()}
// style={{ margin: 2000 }}
/>
</View>
</Provider>
</ApolloProvider>
);
}
}
const AppContainer = createAppContainer(Router);
export default App;
I am new to react-native and this is not me who program this app.
Could someone help me to fix this error, I think its the flatlist who cause this because it happen only I load the page or search something on the list. I know there is a lot a question about this error but I don't find a solution for me.
Warning: Encountered two children with the same key,%s. Keys should be unique so that components maintain their identity across updates.
ContactScreen.js
import React from 'react';
import { Button, View, FlatList, Alert, StyleSheet, KeyboardAvoidingView } from 'react-native';
import { ListItem, SearchBar } from 'react-native-elements';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { Contacts } from 'expo';
import * as Api from '../rest/api';
import theme from '../styles/theme.style';
import { Contact, ContactType } from '../models/Contact';
class ContactsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: "Contacts",
headerRight: (
<Button
onPress={() => navigation.popToTop()}
title="Déconnexion"
/>
),
}
};
constructor(props) {
super(props);
this.state = {
contacts: [],
search: '',
isFetching: false,
display_contacts: []
}
}
async componentDidMount() {
this.getContactsAsync();
}
async getContactsAsync() {
const permission = await Expo.Permissions.askAsync(Expo.Permissions.CONTACTS);
if (permission.status !== 'granted') { return; }
const contacts = await Contacts.getContactsAsync({
fields: [
Contacts.PHONE_NUMBERS,
Contacts.EMAILS,
Contacts.IMAGE
],
pageSize: 100,
pageOffset: 0,
});
const listContacts = [];
if (contacts.total > 0) {
for(var i in contacts.data) {
let contact = contacts.data[i];
let id = contact.id;
let first_name = contact.firstName;
let middle_name = contact.middleName;
let last_name = contact.lastName;
let email = "";
if ("emails" in contact && contact.emails.length > 0) {
email = contact.emails[0].email;
}
let phone = "";
if ("phoneNumbers" in contact && contact.phoneNumbers.length > 0) {
phone = contact.phoneNumbers[0].number;
}
listContacts.push(new Contact(id, first_name, middle_name, last_name, email, phone, ContactType.UP));
}
}
const soemanContacts = await Api.getContacts();
if (soemanContacts.length > 0) {
for(var i in soemanContacts) {
let contact = soemanContacts[i];
let id = contact.contact_id.toString();
let first_name = contact.contact_first_name
let last_name = contact.contact_last_name;
let email = contact.contact_email;
let phone = contact.contact_phone.toString();
listContacts.push(new Contact(id, first_name, "", last_name, email, phone, ContactType.DOWN));
}
}
listContacts.sort((a, b) => a.name.localeCompare(b.name));
this.setState({contacts: listContacts});
this.setState({ isFetching: false });
this.updateSearch(null);
}
async addContactAsync(c) {
const contact = {
[Contacts.Fields.FirstName]: c.firstName,
[Contacts.Fields.LastName]: c.lastName,
[Contacts.Fields.phoneNumbers]: [
{
'number': c.phone
},
],
[Contacts.Fields.Emails]: [
{
'email': c.email
}
]
}
const contactId = await Contacts.addContactAsync(contact);
}
onRefresh() {
this.setState({ isFetching: true }, function() { this.getContactsAsync() });
}
updateSearch = search => {
this.setState({ search });
if(!search) {
this.setState({display_contacts: this.state.contacts});
}
else {
const res = this.state.contacts.filter(contact => contact.name.toLowerCase().includes(search.toLowerCase()));
console.log(res);
this.setState({display_contacts: res});
console.log("contact display "+ this.state.display_contacts);
}
};
toggleContact(contact) {
switch(contact.type) {
case ContactType.SYNC:
break;
case ContactType.DOWN:
this.addContactAsync(contact);
break;
case ContactType.UP:
Api.addContact(contact);
break;
}
/*Alert.alert(
'Synchronisé',
contact.name + 'est déjà synchronisé'
);*/
}
renderSeparator = () => (
<View style={{ height: 0.5, backgroundColor: 'grey', marginLeft: 0 }} />
)
render() {
return (
<View style={{ flex: 1 }}>
<KeyboardAvoidingView style={{ justifyContent: 'flex-end' }} behavior="padding" enabled>
<SearchBar
platform="default"
lightTheme={true}
containerStyle={styles.searchBar}
inputStyle={styles.textInput}
placeholder="Type Here..."
onChangeText={this.updateSearch}
value={this.state.search}
clearIcon
/>
<FlatList
data={this.state.display_contacts}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
renderItem={this.renderItem}
keyExtractor={contact => contact.id}
ItemSeparatorComponent={this.renderSeparator}
ListEmptyComponent={this.renderEmptyContainer()}
/>
</KeyboardAvoidingView>
</View>
);
}
renderItem = (item) => {
const contact = item.item;
let icon_name = '';
let icon_color = 'black';
switch(contact.type) {
case ContactType.SYNC:
icon_name = 'ios-done-all';
icon_color = 'green';
break;
case ContactType.DOWN:
icon_name = 'ios-arrow-down';
break;
case ContactType.UP:
icon_name = 'ios-arrow-up';
break;
}
return (
<ListItem
onPress={ () => this.toggleContact(contact) }
roundAvatar
title={contact.name}
subtitle={contact.phone}
//avatar={{ uri: item.avatar }}
containerStyle={{ borderBottomWidth: 0 }}
rightIcon={<Ionicons name={icon_name} size={20} color={icon_color}/>}
/>
);
}
renderEmptyContainer() {
return (
<View>
</View>
)
}
}
const styles = StyleSheet.create({
searchBar: {
backgroundColor: theme.PRIMARY_COLOR
},
textInput: {
backgroundColor: theme.PRIMARY_COLOR,
color: 'white'
}
});
export default ContactsScreen;
I use react-native and expo for this application.
Just do this in you flatlist
keyExtractor={(item, index) => String(index)}
I think that your some of contact.id's are same. So you can get this warning. If you set the index number of the list in FlatList, you can't show this.
keyExtractor={(contact, index) => String(index)}
Don't build keys using the index on the fly. If you want to build keys, you should do it BEFORE render if possible.
If your contacts have a guaranteed unique id, you should use that. If they do not, you should build a key before your data is in the view using a function that produces unique keys
Example code:
// Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
const keyGenerator = () => '_' + Math.random().toString(36).substr(2, 9)
// in component
key={contact.key}
Just do this in your Flatlist
keyExtractor={(id) => { id.toString(); }}
I got same error and I fixed in this case:
do not code in this way (using async) - this will repeat render many times per item (I don't know why)
Stub_Func = async () => {
const status = await Ask_Permission(...);
if(status) {
const result = await Get_Result(...);
this.setState({data: result});
}
}
componentDidMount() {
this.Stub_Func();
}
try something like this (using then):
Stub_Func = () => {
Ask_Permission(...).then(status=> {
if(status) {
Get_Result(...).then(result=> {
this.setState({data:result});
}).catch(err => {
throw(err);
});
}
}).catch(err => {
throw(err)
});
}
componentDidMount() {
this.Stub_Func();
}
I'm new in react native and currently developing a react-native app that require login. After successful login, the view change into Homepage. The problem is after i close and re-open the app, it shows me LoginPage again.Is there any way to redirect the initial route to another page
class Main extends Component {
_renderScene(route, navigator) {
if (route.id === 1) {
return <LoginPage navigator={navigator} />
} else if (route.id === 2) {
return <HomePage navigator={navigator} />
} else if (route.id === 3) {
return <DetailPage navigator={navigator} />
} else if (route.id === 4) {
return <CreateBookingPage navigator={navigator} />
}
}
_configureScene(route) {
return Navigator.SceneConfigs.PushFromRight;
}
render() {
return (
<Navigator
initialRoute={{id: 1, }}
renderScene={this._renderScene}
configureScene={ () => { return Navigator.SceneConfigs.PushFromRight; }} />
);
}
}
/////after some changes I get into this but still its rendering the login is I done something wrong////////
componentWillMount() {
AsyncStorage.getItem('key').then( (value) => {
if(value==="yes") {
this.setState({ loader: false, logged: true})
} else {
this.setState({ loader: false })
}
})
}
render() {
const routeId = this.state.logged ? 2 : 1;
if(this.state.loader) {
return (
<View /> // loading screen
);
}
return (
<Navigator
initialRoute={{id: routeId }}
renderScene={this._renderScene}
configureScene={ () => { return Navigator.SceneConfigs.PushFromRight; }} />
);
}
On successful login you could set a token/value in the local storage of the device and on logout clear this value.
You could check this value for setting the initial route. Asyncstorage can be used in setting and removing the logged status.
EDIT:
Initial state of loader should be true, logged should be false
componentWillMount() {
AsyncStorage.getItem('key').then( (value) => {
if(value) {
this.setState({ loader: false, logged: true})
} else {
this.setState({ loader: false })
}
})
}
render() {
const { loader } = this.state;
const routeId = logged ? 2 : 1;
if(loader) {
return (
<View /> // loading screen
);
}
return (
<Navigator
initialRoute={{id: routeId }}
renderScene={this._renderScene}
configureScene={ () => { return Navigator.SceneConfigs.PushFromRight; }} />
);
}
Replace with your render function and try it.
render() {
var loggedStatus = true; // change here for login screen
var routeId = loggedStatus ? 2 : 1;
return (
<Navigator
initialRoute={{id: routeId }}
renderScene={this._renderScene}
configureScene={ () => { return Navigator.SceneConfigs.PushFromRight; }} />
);
}