Passing functions to ReactNative Library ActionButton - react-native

Background
I am using xotahal/react-native-material-ui material design in my React-Native application. I have implemented the ActionButton with multiple buttons in it. I can not find anywhere in the docs that is explains how to use this. I was able to find the component in the git repo and managed getting the buttons to render but I can't get them to fire of onClick().
Example
The buttons appear when the main blue button is clicked.
Question
What is the proper way to pass functions to these buttons, or where in the documentation is this explained?
Code
<ActionButton
actions={[
{ icon: 'note-add', label: 'Add', onPress: () => this.toggleSearch() },
{ icon: 'save', label: 'Save', onPress: () => this.handleOnSave() },]}
/>
toggleSearch() {
console.log('################## HEY SEARCH WORKS ##########################');
}
Problem with this is that no functions are fired when I click the button.
I would be grateful if someone knows where this is explained in the documentation.

ActionButton actions prop expects an object with the shape of {icon, label, name}. If you want to handle onPress you need to define it as a prop to the component and not to the actions object.
Example
<ActionButton
actions={[
{ icon: 'note-add', label: 'Add' },
{ icon: 'save', label: 'Save'}]}
onPress={(text) => this.onPress(text)}
/>
// ...
onPress(text) {
switch(text) {
case:
// do something on this case
break;
case:
// do another thing on this case
break;
}
}

Related

refs working on iOS but undefined on Android - React Native

So I have two components
<TouchableInput
onPress={() => this.interestedInPicker.togglePicker()}
/>
<RNPickerSelect
placeholder={{}}
items={[
{
label: 'text',
value: 'value`,
},
{
label: 'text'
value: 'value',
},
{
label: 'text',
value: 'value',
},
]}
onValueChange={restInput.onChange}
style={styles.interestedInPicker}
value={restInput.value}
ref={ref => (this.interestedInPicker = ref)}
/>
RNPickerSelect has height of 0 so it is hidden.
When I press on the TouchableInput I want the function togglePicker to trigger. This works on iOS but logs undefined on Android. When I console.log this.interestedInPicker I can see the method I need but when I log the whole expression it is undefined. Any idea what is going on ?
I opened this as an issue for library RNPickerSelect about a month ago.
It is a known problem. The issue is that they need a way to trigger the picker programatically. You might be able to find a temporary solution HERE

Show Hyperlinks in React Native Alert?

I want to use the Alert Api to display OS behavior alerts.
I'm asking myself if you can display Hyperlinks inside the Text of an alert?
Alert.alert(
'Alert',
'This is an Alert. I want to include hyperlinks here.',
[
{
text: 'Cancel',
onPress: () => console.log("Alert cancel"),
style: 'cancel',
},
{
text: 'Accept',
onPress: () => console.log("Alert accept"),
style: 'default'
},
]
);
You could implement a dialog container, and use the React Native Linking component on the Dialog.Description onPress() to turn it into a hyperlink:
<Dialog.Description onPress={() => Linking.openURL('https://www.google.com')}
style={{ textDecorationLine: 'underline', color: 'blue' }}>www.google.com</Dialog.Description>
or you could add a Text component inside the Dialog.Description alongside some other text to just have a certain word be the hyperlink:
<Dialog.Description>
Visit this website:
<Text onPress={() => Linking.openURL('https://www.google.com')}
style={{ textDecorationLine: 'underline', color: 'blue' }}>www.google.com</Text>
</Dialog.Description>
A word of caution, you're suppose to only pass a string to the Dialog.Description and doing the above will give you a console warning. So use at your own caution but it's working fine for me, and you can hide the warning using the React Native YellowBox component by adding this line outside of your class export (so near the import statements):
YellowBox.ignoreWarnings(['Failed prop type: Invalid prop `children` of type `array` supplied to `DialogDescription`, expected `string`'])
Much better to create a Modal (or simply a View component with position: absolute) to handle this than to dive into the native code.
https://facebook.github.io/react-native/docs/0.56/modal
You need to install "react-native-dialogs"( an android only module for material design dialogs) as follows:
1] Installation:
npm install react-native-dialogs --save
2] Linking:
react-native link react-native-dialogs
3] Import it in your page:
import DialogAndroid from 'react-native-dialogs';
also need to add below code inside your render:
<Button title="show custom alert" onPress={this.showCustomAlert} />
and at last add below function in your screen:
showCustomAlert() {
DialogAndroid.alert('Alert', `This is a link Google`, {
contentIsHtml: true
});
}
You can find more details here https://github.com/aakashns/react-native-dialogs
This is possible using the Linking module that comes with React-Native. Please check out the following:
Display hyperlink in React Native App
If this doesn't work maybe try this npm package:
https://www.npmjs.com/package/react-native-hyperlink

React Navigation: Prevent multiple instances to navigate to same screen

Let's say I have this screen:
And when the user clicks on the white tooltip, it redirects to another screen. Sometimes the app lags a little bit, and clicking on the tooltip takes like ~2s to see the screen change. The problem is, during those 2s, the user taps again on this tooltip to make it happen.
And the result I get is that there are two instances of the new screen in my StackNavigator. What I mean is that I see my new screen, but when I click on "Back" I don't return to this 'Hitchhiking Map' screen, but to another instance of that same screen.
If I clicked 5 times on the callout during those 2s, then I need to click 5 times "Back" to return to the Map screen. Any way to prevent that? To put only one instance into the StackNavigator?
I am using React Navigation, more precisely a StackNavigator. Here's my code:
The "click on tooltip" part:
<MapView.Marker
onCalloutPress={() => this.props.navigation.navigate('spotDetails', { spotId: marker.id })}
/>
My screens:
const HMapNavigator = StackNavigator({
HMap: { screen: HMapViewContainer },
spotDetails: { screen: SpotDetailsViewContainer },
});
The issue of multiple navigations has been reported and there is more detail here.
react-navigation (v1.0.0-beta.7) is in beta and still being built, so until this feature is implemented, you will have to handle the debounce manually.
options
disable the button once the navigation starts
debouncing in the onPress logic or in the action if you are using redux
lodash provides a useful debounce utility, if you are looking for one.
There are many ways how to overcome double navigations.
My solution is adding a key property in navigate object:
this.props.navigation.navigate({ key: 'AnotherScreen', routeName: 'AnotherScreen', params: { ... }})}
Save if its opening to control the navigation
constructor (props) {
super(props)
this.state = {
opening: false
}
}
Create a function to control de navigation
_open (campaign) {
if (!this.state.opening) {
this.props.navigation.navigate('Campaign', {campaign})
this.setState({ opening: true })
setTimeout(() => {
this.setState({ opening: false })
}, 1000)
}
}
Call this func from your onpress
<TouchableHighlight underlayColor='transparent' onPress={this._open.bind(this, campaign)}>
In versions 1.x of React Navigation, if you specify an identifier the navigation action will be executed only once. E.g.:
navigate({ routeName: 'someScreen', key: 'someScreen', params: { someParam: 'someValue' } })
More information: https://gist.github.com/vonovak/ef72f5efe1d36742de8968ff6a708985
In versions 2.x and 3.x this is a default functionality.
More info: https://reactnavigation.org/docs/en/navigation-key.html

Can't access this.props.navigator

I've been creating my views this way:
var SettingsView = React.createClass({
render: function() {
return (
<View>
<TouchableHighlight onPress={this.donePressed}>
//left out styling code for simplicity
</TouchableHighlight>
</View>
);
},
donePressed: function() {
this.props.navigator.pop();
},
});
This is working fine. donePressed is an event handler that's hooked up with a TouchableHighlight in render (not shown).
Today I tried to refactor it to this:
class SettingsView extend React.Component {
render() {
//same stuff as above
}
donePressed() {
this.props.navigator.pop();
}
}
This rendered the settings screen as normal. But when donePressed triggered, screen turned red saying they can't find this.props.navigator.
I'm not sure what is going on here, please help me out!
Edit:
This screen is brought up via another touch event handler from a different page via this method:
settingsTapped: function() {
this.props.navigator.push({
name: 'SettingsView',
component: SettingsView,
})
},
I've also tried to add passProps: this.props.navigator within settingsTapped too. What I'm most confused is why changing the way I create the class could suddenly make this.props.navigator invisible.
I think the reason it wasn't working is that because you are using Classes as opposed to the createClass function, this is no longer bound to the correct scope. You may need to use an es6 fat arrow function to get this lexically bound to the correct scope, like so:
onPress={ () => this.donePressed() }
You could also do this to get it to work:
onPress={ this.donePressed.bind(this) }

Custom backButtonIcon for NavigatorIOS

This question is related to
https://github.com/facebook/react-native/issues/1383
Is there anyway to have a custom back button icon / title with NavigatorIOS?
backButtonIcon, backButtonTitle is not working as expected. The left arrow is always visible. New routes with custom backButtonIcon or backButtonTitle doesnt show
this.props.navigator.push({
title: 'Next',
component: Next,
backButtonIcon: require('./../img/Back.png')
})
Use LeftButtonIcon instead of backButtonIcon like this;
this.props.navigator.push({
title: '详情',
component: PageList,
leftButtonIcon: {uri: 'nav-back'},
onLeftButtonPress: () => {
ViewController.toggleTabBar(true);
this.props.navigator.pop();
},
passProps: {
data: data
}
});
The letButtonIcon comes from Native App.
You can easily achieve this using the Navigator component. Navigator is the JS implementation of a navigator. You can customize every aspect of it and you can use it in both iOS and Android. Further more, NavigatorIos is not maintained as much as Navigator. More info here: https://facebook.github.io/react-native/docs/navigator-comparison.html#content
And here:
https://facebook.github.io/react-native/docs/navigator.html#content