Expo / React Native - Add clickable icon along with StackNavigator objects - android

Is there a way to add a clickable icon along with StackNavigator objects?
This is a working code and it will show a "createBottomTabNavigator" with only one icon that will lead to "OtherScreen" on press.
const OtherStack = createStackNavigator({
Other: OtherScreen,
});
OtherStack.navigationOptions = {
tabBarLabel: 'Other',
tabBarIcon: ({
focused
}) => (
<TabBarIcon focused={focused} name='archive' />
),
};
export default createBottomTabNavigator({
OtherStack
});
I would like to add a share icon to the same "createBottomTabNavigator" so it will be aligned with all other icons but I don't want it to lead to a different screen. I just want it to open a share dialog.
I can't find a solution for this. Is it possible at all? Can someone help please?

You can add a button to the tab bar that doesn't lead to another screen by overriding tabBarOnPress for the route. Here's an example: https://snack.expo.io/#notbrent/playful-almond
The important part is here:
Placeholder: {
screen: () => null,
navigationOptions: {
tabBarOnPress: ({ navigation, defaultHandler }) => {
// don't call default handler!
alert('pressed placeholder!');
},
},
},

Related

React Component re-renders in iOS but not in Android

I am developing an app using React Native and I'm struggling to figure out why my component re-renders in iOS but not in Android. I'm expecting it not to re-render, which means that the Android behavior is the one I'm looking for. The problem is, I don't want this headerIcons to be re-rendered. I've tried useCallback, useMemo, React.memo but it keeps refreshing in iOS devices...
The re-rendering part is the headerIcons argument inside the headerRightIcons parameter of the <Header.NoTitle> component. And here is the thing, this <Header.NoTitle> shows two icons on the screen, one is the < goBack button and the other is the ? help center button (the headerRightIcons parameter) but the only icon being re-rendered is the ? icon. The other one stays fixed.
All the components are being wrapped in a Pull-to-refresh scheme, but the requisition is only being made inside the last Container. Which means that the only part of the screen I wanted to be refreshed is the Container.
const headerIcons = useMemo(
() => [
{
icon: 'question-circle',
onPress: () =>
goToSection(
navigation as never,
EnumInvoiceMainScreenArrivedFrom.MyInvoices,
),
},
],
[navigation],
);
return (
<Wrapper>
<ScrollView
refreshControl={
<RefreshControl onRefresh={onRefresh} refreshing={isRefresh} />
}
stickyHeaderIndices={[0]}
>
<HeaderContainer>
<Header.NoTitle onBackPress={goBack} headerRightIcons={headerIcons} />
<Title>{t(`${i18nPrefix}.title`)}</Title>
<TabRender
tabs={tabsToRender}
tabIndex={tabIndex}
onTabSelected={setTabIndex}
/>
</HeaderContainer>
<Container flex={1} key={`list-updated-${refreshCounter}-times`}>
{children}
</Container>
</ScrollView>
</Wrapper>
);
};
Does the same thing happen if you do it like this?
const handleRightIconPress = ()=>{
goToSection(navigation, EnumInvoiceMainScreenArrivedFrom.MyInvoices)
}
<Header.NoTitle onBackPress={goBack}
headerRightIcons={{
icon: 'question-circle',
onPress: handleRightIconPress,
}}
/>

React Native Bottom Tab Navigation

I have a react native project and i use react-navigations bottom tab navigation in one of the screens.
My question is can i dynamically change one of the icons in it based on which screen am i located ?
For an example i want the middle icon to be dynamic and different for all of the other tabs and when user press some tab i want that icon to change and to have unique functionality.
Do i need to set a callback and pass in every screen that has access and after that callback to re-render the navigator ? - If so will i lose all of the cached & mounted stuff because of the re-render ?
Looking for an optimal solution. Any answer is appreciated.
Thanks.
To do this you have to customize the tab a bit, to do so you need to use the custom
defaultNavigationOptions in createBottomTabNavigator. defaultNavigationOptions takes in a function of a React component where you get a prop such as focused, tintColor, you can do some manipulation using this. If the tab is focused you will get a true value based on that you can change your icon.
For example:
const customTabs = ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
if (routeName === 'PageOne') {
return <View>{focused ? <Icon name='focused' /> : <Icon name='unfocused' /> }</View>
} else if (routeName === 'PageTwo') {
return <Text>{routeName} One</Text>
} else if (routeName === 'PageThree') {
return <Text>{routeName} One</Text>
}
}
});
I have added a small example, couldn't figure out how to add a icon to it, so just changing the text, you can replace them with Icon, this will work.
https://snack.expo.io/#subkundu/icon-focused
Let me know if this works. Happy coding. :)

How to dynamically show Bottom Tab Navigation with json data from server in React Native?

I want to implement Bottom Tab Navigation.So I have done using react native Navigation.But,I need to load the data to the Bottom Tab Navigation that gets the data from json file from server.As of now,I have only implemented the static data and components.Can anyone guide me on how to implement this?
const SettingsStack = createStackNavigator({
Settings: { screen: SettingsScreen }
});
const MoreStack = createStackNavigator({
More: { screen: MoreScreens }
});
export default createBottomTabNavigator(
{
Home: { screen: HomeStack },
Search: { screen: searchStack },
Downloads: { screen: DownloadStack },
Settings: { screen: SettingsStack },
More: { screen: MoreStack }
},
By design react-navigation does not support dynamic route, but you can instead make a higher order function that receive the json data you want as the parameter and them return the navigator as you want. The trade off is that the whole navigation stack will be reset.
I had the best experience/results using react-native-navigation. It uses native components, so you get much better performance and feel. And you can set up bottom tab navigation easily.
Also, this piece is a really good summary of what's out there.

How do I create a StackNavigator for two screens?

I'm using react-navigation to build my first react-native app. I have a home screen on which I want to have a sign up button.
In my router file, I have the following:
export const RootNavigator = StackNavigator({
Home: {
screen: Home
},
SignUp: {
screen: SignUp
}
}, {
mode: 'modal',
headerMode: 'none',
}
);
Here is my Home.js file:
export default class Home extends Component {
render() {
const buttons = ['SIGN IN', 'SIGN UP']
const { selectedIndex } = this.state
return (
<View style={styles.logoContainer} >
<Button
raised
backgroundColor="#333"
title='SIGN IN' />
<Button
raised
onPress = {this.props.navigation.navigate('SignUp')}
backgroundColor="#333"
title='SIGN UP' />
</View>
);
}
}
In my index file, I render this RootNavigator component.
When I load up the simulator, the navigation goes to the Home screen but immediately animates to the SignUp screen.
I'm quite new to this but what I want to be able to do is have the home screen appear, and be able to navigate to the sign up screen when I click on the Sign Up button (which is why I have the Sign up screen in the StackNavigator).
Any thoughts on how to accomplish this?
You are executing function rather than passing as a property. Parenthesizes execute functions.
This,
onPress={this.props.navigation.navigate('SignUp')}
should be like below
onPress={() => this.props.navigation.navigate('SignUp')}
Your problem is not that you need more navigators. You have defined your onPress as the result of this.props.navigation.navigate('SignUp') however what you need is a function handle.
Put the following there and it will work as you intended;
() => this.props.navigation.navigate('SignUp')

Android standalone menu button with React native

I need to make a standalone (without additional bars or else) menu button in my React Native (v 0.47.2) Android app:
On touch it has to open side menu:
Which component I need to use?
You are using react-navigation. Use the StackNavigator. The StackNavigator can set Headers. In the Header, there is a prop to which you can pass an Icon (or any Component).
Here an example:
// all your other imports
import Icon from "react-native-vector-icons/Ionicons";
import {
Platform,
} from "react-native";
const MenuButton = ({ navigate }) => {
return (
<Icon
name={Platform.OS === "ios" ? "ios-menu-outline" : "md-menu"}
onPress={() => navigate("DrawerOpen")}
/>
)
}
StackNavigator({
Notifications: {
screen: Example,
navigationOptions: ({ navigation }) => ({
headerLeft: <MenuButton {...navigation} />,
}),
},
The headerLeft (or headerRight) can be used for you case (Documentation). Here I pass <MenuButton /> component. You can set the color of the StackNavigators Header to the backgroundColor of your app, or transparent. That way, there won`t be anything visible, but the menu button.
Of yourse you would need to stack you StackNavigator in a DrawerNavigator for the onPress={() => navigate("DrawerOpen")} to work.
In the DrawerNavigator you can use a contentComponent which you pass your custom component, that contains your menu.
Here is a more complex setup http://rationalappdev.com/cross-platform-navigation-in-react-native/

Categories

Resources