react-native-navigation showInAppNotification blank - android

Trying use this.props.navigator.showInAppNotification
this.props.navigator.showInAppNotification({
screen: "example.InAppNotification",
passProps: {
title: 'Title',
body: 'Body...'
},
position: 'bottom',
autoDismissTimerSec: 3
});
screen InAppNotification is registered, but see notification with blank content:
Can anyone help with this?
example.InAppNotification:
export default class InAppNotification extends Component {
render() {
console.log(this.props);
return (
<View>
<Text>
{JSON.stringify(this.props)}
</Text>
</View>
);
}
}

try by adding flex:1 to container View
export default class InAppNotification extends Component {
render() {
console.log(this.props);
return (
<View style={{ flex: 1 }}>
<Text>
{JSON.stringify(this.props)}
</Text>
</View>
);
}
}
also you need to register InAppNotification screen correctly

Related

How can i make DrawerLayout reusable?

I am new to ReactNavite. I am playing around with Android DrawerLayout.
I am using StackNavigator for screen redirection.
Do I have to put DrawerLayoutAndroid in each screen, because it does not seem logical? Can't I create a custom class and use it in every screen and some property like selected or unselected?
Screen1.js
export default class Screen1 extends Component<{}> {
static navigationOptions = {
header: null
};
onScreen1Click() {
this.refs["NAVDRAWER"].closeDrawer();
this.props.navigation.navigate("screen1");
}
onScreen2Click() {
this.refs["NAVDRAWER"].closeDrawer();
this.props.navigation.navigate("screen2");
}
render() {
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => {
return (
<ScrollView vertical={true}>
<View style={styles.drawerMenuSelectedView}>
<Text
style={styles.menuItemSelected}
onPress={() => this.onScreen1Click()}
>
Screen 1
</Text>
</View>
<View style={styles.drawerMenuUnselectedView}>
<Text
style={styles.menuItemUnselected}
onPress={() => this.onScreen2Click()}
>
Screen 2
</Text>
</View>
</ScrollView>
);
}}
ref={"NAVDRAWER"}
>
<View>
<Text> Screen 1 </Text>
</View>
</DrawerLayoutAndroid>
); }
}
Screen2.js
export default class Screen2 extends Component<{}> {
static navigationOptions = {
header: null
};
onScreen1Click() {
this.refs["NAVDRAWER"].closeDrawer();
this.props.navigation.navigate("screen1");
}
onScreen2Click() {
this.refs["NAVDRAWER"].closeDrawer();
this.props.navigation.navigate("screen2");
}
render() {
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => {
return (
<ScrollView vertical={true}>
<View style={styles.drawerMenuSelectedView}>
<Text
style={styles.menuItemUnselected}
onPress={() => this.onScreen1Click()}
>
Screen 1
</Text>
</View>
<View style={styles.drawerMenuUnselectedView}>
<Text
style={styles.menuItemSelected }
onPress={() => this.onScreen2Click()}
>
Screen 2
</Text>
</View>
</ScrollView>
);
}}
ref={"NAVDRAWER"}
>
<View>
<Text> Screen 2 </Text>
</View>
</DrawerLayoutAndroid>
); }
}
App.js
import React, { Component } from 'react';
import { StackNavigator } from "react-navigation";
import Screen1 from "./Screen1";
import Screen2 from "./Screen2";
export default class App extends Component<Props> {
render() {
return (
<MyApp />
);
}
}
const MyApp = StackNavigator({
screen1: { screen: Screen1 },
screen2: { screen: Screen2 },
});
After long time researching , I landed on this library for drawer navigation with reusable Drawer,
https://github.com/react-navigation/react-navigation
This lib provides DrawerNavigator , Which also helps us to make custom Drawer Design and you can add screens of Drawer in DrawerNavigator...
Also, I have used this blog for reference
https://codeburst.io/custom-drawer-using-react-navigation-80abbab489f7
I hope this helps you ...

Native-Base - CheckBox inside List not getting checked

I have imported CheckBox from NativeBase. On clicking the Checkbox, it calls the toggleCheckBox function to either add or remove the item.ids from the array and also set the flag to true or false based on the contents of the array.
I can see that the toggleCheckBox function works properly and it sets the array with item ids properly and the flag is also fine on click of the CheckBox. But, the checkbox inside the ListItem is not checked when the checkbox is clicked though the toggle function is called properly.
I also noticed that the log "MS CB2: " right above the List is printed after clicking the CheckBox but the log inside the List 'MS insideList :' is not printed. I am assuming that List is not rendered after the toggleCheckBox function is called.
Here is the code:
class MSScreen extends Component {
constructor(props){
super(props);
//this.toggleCheckbox = this.toggleCheckbox.bind(this);
this.state = {
isLoading: true,
checkboxes : [],
plans: {},
};
}
componentDidMount(){
console.log("MS inside componentDidMount");
fetch('http://hostname:port/getData')
.then((response) => {console.log('response'); return response.json();})
.then((responseJson) => {console.log('responseData: '+responseJson); this.setState({isLoading : false, plans : responseJson}); return;})
.catch((err) => {console.log(err)});
}
toggleCheckbox(id) {
let checkboxes = this.state.checkboxes;
if(checkboxes && checkboxes.includes(id)){
const index = checkboxes.indexOf(id);
checkboxes.splice(index, 1);
} else {
checkboxes = checkboxes.concat(id);
}
this.setState({checkboxes});
console.log("MS check a4: "+checkboxes && checkboxes.includes(id))
}
render() {
if (this.state.isLoading) {
return <View><Text>Loading...</Text></View>;
}
const plans = this.state.plans;
const { params } = this.props.navigation.state.params;
const checkboxes = this.state.checkboxes;
console.log("MS CB1: "+checkboxes)
return (
<Container>
<Content>
<View>
{console.log("MS CB2: "+checkboxes)}
<List
dataArray={plans.data}
renderRow={(item, i) => {
console.log('MS insideList : '+checkboxes && checkboxes.includes(item.id))
return(
<ListItem
key={item.id}
>
<Left>
<CheckBox
onPress={() => this.toggleCheckbox(item.id)}
checked={checkboxes && checkboxes.includes(item.id)}
/>
</Left>
<Text>
{item.name}
</Text>
</ListItem>)}}
/>
</View>
</Content>
</Container>
);
}
}
How do I get the CheckBox to get checked inside the List?
For the benefit of the other users, here is the code fix based on the suggestion from Supriya in the comments below:
SOLUTION
<FlatList
extraData={this.state}
data={plans.data}
keyExtractor={(item, index) => item.id}
renderItem={({item}) => {
const itemName = item.name;
return(
<ListItem>
<CheckBox
onPress={() => this.toggleCheckbox(item.id)}
checked={checkboxes && checkboxes.includes(item.id)}
/>
<Body>
<Text style={styles.planText}>
{item.name}
</Text>
</Body>
</ListItem>)}}
/>
Version:
native-base#2.3.5
react-native#0.50.4
Device: Android
CRNA app with Expo
There is a similar issue on github, https://github.com/GeekyAnts/NativeBase/issues/989 with solution
It works with straightforward code without listItem.
The following example handles the checkboxes as radio buttons, but the onPress functions can be changed easily to allow multiple selection.
import React, { Component } from 'react';
import { View } from 'react-native';
import { CheckBox, Text } from 'native-base';
export default class SignupScreen extends Component {
state = {
one: false,
two: false,
three: false
};
render() {
return (
<View style={{ alignItems: 'flex-start' }}>
<View style={{ flexDirection: 'row' }}>
<CheckBox checked={this.state.one}
style={{ marginRight: 20 }}
onPress={this.onePressed.bind(this)}/>
<Text>One</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<CheckBox checked={this.state.two}
style={{ marginRight: 20 }}
onPress={this.twoPressed.bind(this)}/>
<Text>Two</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<CheckBox checked={this.state.three}
style={{ marginRight: 20 }}
onPress={this.threePressed.bind(this)}/>
<Text>Three</Text>
</View>
</View>
);
}
// checkbox functions
// if clicked button was set, only clear it
// otherwise, set it and clear the others
onePressed() {
if (this.state.one)
this.setState({ one: false });
else
this.setState({ one: true, two: false, three: false });
}
twoPressed() {
if (this.state.two)
this.setState({ two: false });
else
this.setState({ one: false, two: true, three: false });
}
threePressed() {
if (this.state.three)
this.setState({ three: false });
else
this.setState({ one: false, two: false, three: true });
}
}

Click event on words react native

I want to set different click listeners on different words of . Currently what i have is
<Text>Android iOS React Native<Text>
Now i want to know when user click on Android, iOS and React Native, i have to perform some analytics on that so need click listeners for seperate words.
Does any one have idea about it? I have checked this thread but i din't found it useful for my requirement.
Update
String i have given is just an example string, in real time i will be getting dynamic strings.
This is what i will be getting as dynamic string
{
"str":"Hi i am using React-Native, Earlier i was using Android and so on"
"tagWords":["React-Native","Android"]
}
And in output i want, "Hi i am using React-Native, Earlier i was using Android and so on"
with click event on "React-Native" and "Android". Is is possible?
The post you sent is the simplest way you can achieve the desired behavior. Sinse you need to have different listeners you need to implement different Text components.
Example
export default class App extends Component {
onTextPress(event, text) {
console.log(text);
}
render() {
return (
<View style={styles.container}>
<Text>
<Text onPress={(e) => this.onTextPress(e, 'Android')} style={styles.red}>{'Android '}</Text>
<Text onPress={(e) => this.onTextPress(e, 'iOS')} style={styles.purple}>{'iOS '}</Text>
<Text onPress={(e) => this.onTextPress(e, 'React Native')} style={styles.green}>{'React Native'}</Text>
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
red: {
fontSize: 20,
color: 'red'
},
purple: {
fontSize: 20,
color: 'purple'
},
green: {
fontSize: 20,
color: 'green'
}
});
Update 1 (Dynamic text)
render() {
const fixedString = 'I\'m a fixed string that slipleted';
const arrayOfStrings = ['These', 'are', 'strings', 'from', 'array'];
return (
<View style={styles.container}>
<Text style={styles.textContainer}>
{
fixedString.split(' ').map((str, index) => {
return (
<Text onPress={(e) => this.onTextPress(e, str)}>
{`${str}${index !== (fixedString.split(' ').lenght -1) && ' '}`}
</Text>
)
})
}
</Text>
<Text style={styles.textContainer}>
{
arrayOfStrings.map((str, index) => {
return (
<Text onPress={(e) => this.onTextPress(e, str)}>
{`${str}${index !== (arrayOfStrings.lenght -1) && ' '}`}
</Text>
)
})
}
</Text>
</View>
);
}
Update 2 (for example dynamic data)
removePunctuation = (text) => {
// this is a hack to remove comma from the text
// you may want to handle this different
return text.replace(/[.,\/#!$%\^&\*;:{}=\_`~()]/g,"");
}
render() {
const arrayOfObjects = [{
str: 'Hi i am using React-Native, Earlier i was using Android and so on',
tagWords: ['React-Native', 'Android']
}];
return (
<View style={styles.container}>
<Text style={styles.textContainer}>
{
arrayOfObjects.map((obj) => {
return obj.str.split(' ').map((s, index) => {
if ( obj.tagWords.indexOf(this.removePunctuation(s)) > -1 ) {
return (
<Text onPress={(e) => this.onTextPress(e, s)} style={styles.red}>
{`${s} ${index !== (obj.str.split(' ').lenght - 1) && ' '}`}
</Text>
)
} else return `${s} `;
})
})
}
</Text>
</View>
);
}
all you need to use is TouchableOpacity(for the tap effect and clicks), View for the alignment of texts. and certain styling. I am providing you the code snippet that will work for you , all other syntax will remain same
import {Text, View, TouchableOpacity} from 'react-native'
<View style={{flexDirection:'row'}}>
<TouchableOpacity onPress={{()=>doSomethingAndroid()}}>
<Text>Android</Text>
</TouchableOpacity>
<TouchableOpacity onPress={{()=>doSomethingiOS()}}><Text> iOS</Text>
</TouchableOpacity>
<TouchableOpacityonPress={{()=>doSomethingReactNative()}}><Text> React Native</Text>
</TouchableOpacity>
</View>
i hope this works, comment back if any issue happens
You can wrap each clickable words into 'TouchableOpacity' component, and tract the onPress event as follows
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={() => {
console.log('Android Clicked');
}}>
<Text>Android</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
console.log('iOS Clicked');
}}>
<Text>Ios</Text>
</TouchableOpacity>
</View>
Please do adjust the spacing between words.
Edit:
For dynamic string you can proceed as follows
...
handleWordClick(str, handler) {
var words = str.split(' '), // word separator goes here,
comp = [];
words.forEach((s, ind) =>{
comp.push(
<TouchableOpacity key={ind} onPress={() => handler.call(this, s)}>
<Text>{s}</Text>
</TouchableOpacity>
);
})
return comp;
}
render() {
var comp = this.handleWordClick('Android iOS React-Native', (word) => {
//handle analytics here...
console.log(word);
});
return (
<View>
...
<View style={{flexDirection: 'row'}}>
{comp}
</View>
...
</View>
)
}
I am not sure what will be your word separator as the example you have given has 'React Native' as single word. Please pay attention on this part.
Hope this will help you.

Platform specific components in React Native

I'm pretty sure this is straightforward, but I can't quite see how to bring it together. At the moment my app works perfectly in iOS, but I've used a few controls which are not Android compatible:
<View style={containerStyle}>
<Text style={labelStyle}>Drink:</Text>
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
<View style={{ flex: 1 }} />
</View>
I want to use the React-Native-Segmented-Android library to fix this. I feel like I should be able to do something like:
<View style={containerStyle}>
<Text style={labelStyle}>Drink:</Text>
const Component = Platform.select({
ios: () => require('SegmentedControlIOS'),
android: () => require('react-native-segmented-android'),
})(
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>);
<View style={{ flex: 1 }} />
</View>
but that (perhaps unsurprisingly) doesn't work. Can anyone point me to the correct method? I know I can just use two different files for iOS/Android but I'd rather keep it together in one if possible.
I would create a sepeare component and this component would return segment according to platform but you can create an inner function as an alternative. call this function in render to handle decide which platform app runs and return segment according to platform.
_segmentPicker() {
if (Platform.OS == 'android') {
return (
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
);
} else if (Platform.OS == 'ios') {
return (
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
);
}
}
render(){
return (
<View>
{this._segmentPicker()}
.
.
</View>
);
}

React-Native Navigator not rendering

I am trying to create routing between scenes using Navigator on React-Native (Android), However Navigator won't render the scene, Here is a simple snippet I've created.
<View>
<Navigator
initialRoute={{ name: 'LoginView' }}
renderScene={(route, naigator) => {
<Text styles={{fontSize: 20, fontWeight: 'bold'}}>Hello, World!</Text>
}}
/>
</View>
This should render the text Hello, World!, but a plain white screen showed up on the emulator.
You can use the Navigator component like this:
<Navigator
style={{flex: 1}}
ref={thisRef => {this.navigator = thisRef}}
initialRoute={{ title: 'Awesome Scene', index: 0}}
renderScene={(route, navigator) => {
if(route.index == 0) {
return <View>
<Text>Hello, World!</Text>
</View>
}
if(route.index == 1) {
return <View>
<Text>Hi, There</Text>
</View>
}
if(route.index == 2) {
return <View>
<Text>Hi, There...again!</Text>
</View>
}
}} />
That way you can go to another page using
this.navigator.push({title: "Awesome Scene 2", index: 1})
or
this.navigator.push({title: "Awesome Scene 3", index: 2})
and it will render the correct scene.
Hope this helps!
Just figured out why this happens, Since renderScene takes in a function it must return a single object of react native UI. So the UI code must be wrapped inside View as seen in these examples below:
<Navigator
initialRoute={{ title: 'Awesome Scene'}}
renderScene={(route, navigator) => {
<View>
<Text>Hello, World!</Text>
<Text>Hi, There</Text>
</View>
}}
/>

Categories

Resources