I'm a newbie in AWS Amplify, and just couldn't figure out how to make my App class wait for the user to sign in before loading all other navigation components and then make the authentication component disappear as well. I'm exporting my app with the withAuthenticator function. What would be the best way to do this? Tkx!
Tried to find examples of post-login operations, without success.
class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Navigator />
);
}
}
export default withAuthenticator(App);
Navigation components are loaded over the Sign In screen. The sign in screen does not disappear after the user is signed in, being overlapped by other components.
I think I figured out the best way of doing that is using Authenticator instead of withAuthenticator:
class AppWithAuth extends Component {
state = {
authState: ''
};
render() {
return (
<View style = { styles.container }>
<Authenticator
amplifyConfig = {awsconf}
onStateChange = {authState => this.setState({ authState })}
>
{this.state.authState === 'signedIn' && <App />}
</View>
...
}
class App extends Component {
render() {
return (
<View style = { styles.container }>
<Navigator />
</View>
);
}
}
I use TabNavigator and DrawerNavigator both in my app.
When I open drawer with 'slide' option, contents slide with drawer but TabBar doesn't slide together.
I want to make TabBar slide together but I cannot find any option about it.
How Can I do this?
Could you help?
-------------[code]----------------
1) app.js
...skip ...
const DailySalesStack = createStackNavigator({
DailySalesMain: DailySalesMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailySalesMain'
});
const DailyRivalRankStack = createStackNavigator({
DailyRivalRankMain: DailyRivalRankMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailyRivalRankMain'
});
const SalesAnalysisStack = createStackNavigator({
SalesAnalysisMain: SalesAnalysisMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'SalesAnalysisMain'
});
const DailySalesAnalysisStack = createStackNavigator({
DailySalesAnalysisMain: DailySalesAnalysisMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailySalesAnalysisMain'
});
/// DRAWER!
const SalesStack = createDrawerNavigator({
DailySales: {
screen: DailySalesStack,
},
DailyRivalRank: {
screen: DailyRivalRankStack,
},
SalesAnalysis: {
screen: SalesAnalysisStack,
},
DailySalesAnalysis: {
screen: DailySalesAnalysisStack,
},
},
{
contentComponent:SalesSlideMenu,
drawerType: 'slide',
drawerWidth:230*REM,
}
);
...skip...
/// BOTTOM TAB
export default createAppContainer(createBottomTabNavigator(
{
MainStack:MainStack,
ApprovalStack:ApprovalStack,
SalesStack:SalesStack,
OrganizationStack:OrganizationStack,
SettingStack:SettingStack,
},
{
tabBarComponent: TabBar,
}
));
2) tabBar.js
const TAB_LIST = [
require('../../resources/images/tabIcon_main.png'),
require('../../resources/images/tabIcon_approval.png'),
require('../../resources/images/tabIcon_sales.png'),
require('../../resources/images/tabIcon_organization.png'),
require('../../resources/images/tabIcon_settings.png'),
];
export default class TabBar extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("[TabBar.js] : Render ====");
const {
onTabPress,
navigation
} = this.props;
const { routes, index: activeRouteIndex } = navigation.state;
return (
<SafeAreaView style={{backgroundColor:'rgb(250,250,250)'}}>
<View style={styles.rootContainer}>
{routes.map((route, routeIndex) => {
const isRouteActive = routeIndex === activeRouteIndex;
return (
<TouchableWithoutFeedback key={routeIndex} onPress={() => {onTabPress({ route });}}>
<View style={styles.tabIconContainer}>
<Image style={[styles.icon,isRouteActive&&{tintColor:'black'}]} source={TAB_LIST[routeIndex]} resizeMode={'contain'}/>
{/* <View style={[styles.badge]}><Text style={[styles.text,styles.badgeNumber]}>12</Text></View> */}
</View>
</TouchableWithoutFeedback>
);
})}
</View>
</SafeAreaView>
);
}
}
3) SlideMenu.js
const MENU_LIST = [
{'icon':require('../../resources/images/dailySales.png'),'label':'Daily Sales','subLabel':'','route':'DailySales'},
{'icon':require('../../resources/images/rivalRank.png'),'label':'Daily Rival Rank','subLabel':'','route':'DailyRivalRank'},
{'icon':require('../../resources/images/salesAnalysis.png'),'label':'Sales Analysis','subLabel':'','route':'SalesAnalysis'},
{'icon':require('../../resources/images/dailySalesAnalysis.png'),'label':'Daily Sales Analysis','subLabel':'','route':'DailySalesAnalysis'},
]
class SlideMenuTab extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<View style={{flex:0}}>
<TouchableWithoutFeedback onPress={()=>this.props.navigation.navigate(this.props.data.route+"Main")}>
<View style={[styles.tabContainer,this.props.focused&&{backgroundColor:'rgb(247,247,247)'}]}>
<Image style={styles.tabIcon} source={this.props.data.icon} resizeMode={'contain'}/>
<View style={styles.labelContainer}>
<Text style={[styles.text,styles.label]}>{this.props.data.label}</Text>
<Text style={[styles.text,styles.subLabel]}>{this.props.data.subLabel}</Text>
</View>
</View>
</TouchableWithoutFeedback>
</View>
)
}
}
export default class SalesSideMenu extends React.Component {
constructor(props) {
super(props);
console.log("[SalesSideMenu.js] : Constructor");
}
render() {
console.log("[SalesSideMenu.js] : render ====");
let menuList = [];
MENU_LIST.forEach((data)=>{
let focused = this.props.activeItemKey === data.route;
menuList.push(
<SlideMenuTab data={data} focused={focused} navigation={this.props.navigation}/>
);
})
return (
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={styles.rootContainer}>
{menuList}
</View>
</SafeAreaView>
);
}
}
4) Screen with drawer
export default class DailySalesMain extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("[DailySalesMain.js] : render ====");
return (
<View style={{flex:1,backgroundColor:'white',alignItems:'center',justifyContent:'center'}}>
<TouchableWithoutFeedback onPress={()=>this.props.navigation.openDrawer()}>
<View style={{width:'100%',height:50}}>
<View style={{width:50,height:50,backgroundColor:'blue'}}></View>
</View>
</TouchableWithoutFeedback>
<Text>DailySalesMain</Text>
</View>
);
}
}
If youre ussing React Native... This should be the default behaviour at least in iOS. Android Material Design supports the Drawer as a design desition, so if you want to hide the TabBar, just make a custom one or include the TabBar inside the Drawer.
But warning, hidding the TabBar may sometimes bring errors in Apple Store when you upload your app for revision.
From the TabBar section in the Human Interface Guidelines of iOS....
Don't hide a tab bar when people navigate to different areas in your app. A tab bar enables global navigation for your app, so it should remain visible everywhere. The exception to this is in modal views. Because a modal view gives people a separate experience that they dismiss when they're finished, it's not part of the overall navigation of your app.
Use badging to communicate unobtrusively. You can display a badge—a red oval containing white text and either a number or an exclamation point—on a tab to indicate that new information is associated with that view or mode.
In other words.. if you plan to support iOS in your apps, you should try to always show the TabBar somehow, or the store might give you some usability complains like this one.
We noticed that several screens of your app were crowded or laid out in a way that made it difficult to use your app.
Please see attached screenshot for reference.
Next Steps
To resolve this issue, please revise your app to ensure that the content and controls on the screen are easy to read and interact with.
I'm attempting to use a React Navigation StackNavigator for a process that includes a static component at the top of the page and varying components at the bottom. The code I'm using is:
const Navigator = StackNavigator ({
splash: Splash,
prompt: Prompt,
pinCheck: PinCheck
}, {
initialRouteName: 'splash'
});
export default class Login extends React.Component
{
constructor (props)
{
super (props);
// code to set up animation state
}
componentDidMount()
{
// code to set up animation
}
finish_ (state)
{
this.props.navigation.navigate ('main', state);
}
render()
{
const screen = Dimensions.get('screen');
return (
<KeyboardAvoidingView style={Global.styles.verticalFill} ref={this.saveContainerRef}>
<ScrollView style={{flex: 1}} contentContainerStyle={{justifyContent: 'space-between'}}>
<Animated.View style={{opacity:this.state.fade1,alignItems:'center'}} >
<Image
style={{width:screen.width * 0.6,height: screen.height*0.55}}
source={imgLogo}
resizeMode='contain'
/>
<Navigator />
</Animated.View>
</ScrollView>
</KeyboardAvoidingView>
);
}
}
When I run this, however, my initial route component is not shown. It works correctly if I swap <Navigator/> to <Splash/> however, so the component itself definitely works in this context.
Any ideas what's wrong?
There is a problem in your navigation setup.
All the routes in the StackNavigator must declare a screen
as mentioned in the docs
const Navigator = StackNavigator ({
splash: {
screen: splash
},
prompt: {
screen: prompt
},
pinCheck: {
screen: pinCheck
}
}, {
initialRouteName: 'splash'
})
I want to make a responsive App in React Native. I subscribe to Dimension changes in the container using this:
const RCTDeviceEventEmitter = require("RCTDeviceEventEmitter");
export interface Props {
data: Array<any>;
}
export interface State {}
class MyContainer extends React.Component<Props, State> {
_updateIfSelected() {
if (...some more logic...) {
this.forceUpdate();
}
}
constructor(props) {
super(props);
this.state = {
listener: null,
updateIfSelected: this._updateIfSelected.bind(this),
};
}
componentWillMount() {
this.setState({
listener: RCTDeviceEventEmitter.addListener("didUpdateDimensions", this.state.updateIfSelected),
});
}
componentWillUnmount() {
this.state.listener.remove("didUpdateDimensions",this.state.updateIfSelected);
}
renderItem() {
console.log("Rerendering Item")
return <Text style={{ width: Dimensions.get("window").width }} >Some Text</Text>
}
render() {
return (
<FlatList
data={this.props.data}
keyExtractor={(_, i) => (i.toString())}
renderItem={({item}) => this.renderItem(item)}
/>
}
}
I was wondering how to force a FlatList to rerender its items, because the appearance needs to change when the screen is tilted. However, because the data doesn't change, the list won't be rerendered on screen tilts.
The Documentation provides a parameter called extraData:
By passing extraData={this.state} to FlatList we make
sure FlatList itself will re-render when the state.selected
changes.
Without setting this prop, FlatList would not know it
needs to re-render any items because it is also a
PureComponent and the prop comparison will not show any changes
But I don't really understand what this is trying to say. Any Ideas how I can make the FlatList Rerender on Dimension changes?
You can pass a function to onLayout and check the dimensions when onLayout is called. I would recommend passing the function to a parent view. You could then setState in the function
class MyComponent extends Component {
_onLayout() { // I haven't tried this but I think this or something similar will work
const { width, height } = Dimensions.get('window');
if(width > height) {
this.setState(state => ({ ...state, orientation: 'landscape' }));
} else {
this.setState(state => ({ ...state, orientation: 'portrait' }));
}
}
render() {
return (
<View onLayout={this._onLayout}>
<FlatList
data={this.props.data}
keyExtractor={(_, i) => (i.toString())}
renderItem={({item}) => this.renderItem(item)}
extraData={this.state.orientation}
/>
</View>
)
}
}
I am just React Native beginner.I have just created NavigatorDrawer with classes Home.js and Team.js.I have just added toolbar but it's not displaying. Can anyone look at my code and help me where I have done a mistake.
Home.js
const { navigate } = props.navigation;
return (
<ToolbarAndroid
title='Home'
style={styles.toolbar}
titleColor='white'
/>
<View>
<Text style={styles.abt}Home</Text>
</View>
);
index.android.js:
render()
{
const { navigation } =this.props;
return (
<Home navigation={ navigation }/> );
}
}
const App =DrawerNavigator({
Home:{screen:Home},
Team :{ screen: Team},
Wallpapers:{screen: Wallpapers},
});