How can I change the scene(Navigator) by click DrawerLayoutAndroid - react-native

guys.I need a help.
I want use DrawerLayoutAndroid and Navigator as my App navigator.
And I have a problem here.
I code like this,and it doesn't work.
<TouchableHighlight>
<Text style={styles.menu} onPress={() => this.refs['myNavigator'].navigator.push({id:'List',name:'List Page'})}>Menu Item1</Text>
</TouchableHighlight>
How can I change the scene(Navigator) by click DrawerLayoutAndroid.
Hope somebody help...
Here's the main code.
renderScene:
renderScene(route, navigator) {
var routeId = route.id;
if (routeId === 'SplashPage') {
return (
<SplashPage
navigator={navigator} />
);
}
if (routeId === 'MainPage') {
return (
<MainPage openDrawer={this.openDrawer.bind(this)}
navigator={navigator} {...route.passProps}/>
);
}
if (routeId === 'List') {
return (
<ListComponent
navigator={navigator} {...route.passProps} />
);
}
if (routeId === 'Detail') {
return (
<DetailComponent
navigator={navigator} {...route.passProps} />
);
}
if (routeId === 'Share') {
return (
<ShareComponent
navigator={navigator} {...route.passProps} />
);
}
}
render part:
var navigationView = (
<View style={{flex: 1, backgroundColor: '#161616'}}>
<Text style={styles.menuTitle}>Nav Title</Text>
<TouchableHighlight >
<Text style={styles.menu}>Home</Text>
</TouchableHighlight>
<TouchableHighlight>
<Text style={styles.menu} onPress={() => this.refs['myNavigator'].props.navigator.push({id:'List',name:'List Page'})}>Menu Item1</Text>
</TouchableHighlight>
<TouchableHighlight>
<Text style={styles.menu}>Menu Item2</Text>
</TouchableHighlight>
</View>
);
return (
<DrawerLayoutAndroid
drawerWidth={260}
ref={'DRAWER'}
drawerPosition={DrawerLayoutAndroid.positions.left}
renderNavigationView={() => navigationView}>
<Navigator
ref={'myNavigator'}
initialRoute={{id: 'SplashPage', name: 'SplashPage'}}
renderScene={this.renderScene.bind(this)}
navigator={this.props.navigator}
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}}
/>
</DrawerLayoutAndroid>
)

I got it working when coded the other way around:
Render
render() {
return (
<Navigator
ref="navigator"
initialRoute={{name: "creategame", id: "creategame"}}
renderScene={this._renderScene.bind(this)}
configureScene={() => ({...FadeAndroid})}
/>
)
}
RenderScene
_renderScene(route, navigator) {
// Put your logic here selecting a component/scene based on route.id
let contentView = ...
return (
<DrawerLayoutAndroid
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => <MenuView route={routeId} navigator={navigator} />}>
{contentView}
</DrawerLayoutAndroid>
)
}
Then finally call navigator.push (which is passed as a prop to my MenuView component; see example below) and you're done.
MenuView
class MenuView extends Component {
constructor() {
super();
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([])
};
}
componentDidMount() {
var menuItems = [
{title: 'xxx', id: 'x'},
{title: 'yyy', id: 'y'},
... and so on
]
this.setState({
dataSource: this.state.dataSource.cloneWithRows(menuItems)
});
}
_renderMenuRow(rowData) {
return (
<TouchableHighlight onPress={this._onPress.bind(this, rowData.id)}>
<Text style={styles.menuRowText}> {rowData.title} </Text>
</TouchableHighlight>
);
}
_onPress(id) {
this.props.navigator.push({
id: id,
});
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderMenuRow.bind(this)}
);
};
}

Related

How to get value from TextInput using state in react native?

I am trying to implement TextInput and I stuck in moment when I need to get text from this.
I tried a lot of options from other StackOverflow questions but nothing works for me.
This is my code where I am using TextInput:
export default class HomeScreen extends Component {
constructor(props) {
super(props)
this.state = {
text: ''
};
}
show = () => {
console.log(this.state.text)
}
render() {
return (
<View>
<View style={{backgroundColor: 'purple', height: '100%'}}>
<View>
<Button title={'test'} onPress={this.show}></Button>
<MyTextInput
btn={1}
placeholder={'test'}
isDateTime={false}
onChangeText={(value) => this.setState({text: value})
value={this.state.text} />
</View>
</View>
</View>
)
}
and here is MyTextInput code:
export function MyTextInput(props) {
const [show, setShow] = useState(false);
const btn = props.btn;
const inputType = () => {
if(props.isDateTime) {
setShow(true);
}
else {
setShow(false);
}
}
return (
<View style={btn ? styles.container : styles.container2}>
<TextInput
style={btn ? styles.input : styles.input2}
{...this.props}
placeholder={props.placeholder}
onFocus={inputType}
showSoftInputOnFocus={props.isDateTime ? false : true} />
{show && (
<DTPicker />
)}
</View>
);
}
When I hit the button I get this:
[Info] 06-01 07:24:59.158 6962 7031 I ReactNativeJS:
Where is my mistake or what I should do different?
you need to pass onChangeText={(value) => props.onChangeText(value)} in TextInput
export function MyTextInput(props) {
const [show, setShow] = useState(false);
const btn = props.btn;
const inputType = () => {
if(props.isDateTime) {
setShow(true);
}
else {
setShow(false);
}
}
return (
<View style={btn ? styles.container : styles.container2}>
<TextInput
onChangeText={(value) => props.onChangeText(value)}
style={btn ? styles.input : styles.input2}
{...this.props}
placeholder={props.placeholder}
onFocus={inputType}
showSoftInputOnFocus={props.isDateTime ? false : true} />
{show && (
<DTPicker />
)}
</View>
);
}

Call a function from static method

I have something like this:
const BasketButton2 = ({ isWhite, style, navigation }) => (
<TouchableOpacity
style={[styles.button, style]}
onPress={() => Header.addInstaPost()}
>
<Icon
family="Entypo"
size={16}
name="new-message"
color={theme.COLORS[isWhite ? 'WHITE' : 'ICON']}
/>
</TouchableOpacity>
);
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
notifications: false,
loading: true,
error: null,
modalVisible: false,
modalThanksVisible: false,
reportSubmitted: false,
reportError: false,
};
}
handleLeftPress = () => {
const { back, navigation } = this.props;
return back ? navigation.goBack() : navigation.openDrawer();
};
renderRight = () => {
const { white, title, navigation, scene } = this.props;
if (global.loggedUser === true) {
return [
<BasketButton2
key="basket-search"
navigation={navigation}
isWhite={white}
/>,
<ChatButton
key="chat-search"
navigation={navigation}
isWhite={white}
/>,
];
} else {
return [
<BasketButton
key="basket-search"
navigation={navigation}
isWhite={white}
/>,
<ChatButton
key="chat-search"
navigation={navigation}
isWhite={white}
/>,
];
}
};
renderSearch = () => {
const { navigation } = this.props;
return (
<Input
right
color="black"
style={styles.search}
placeholder="What are you looking for?"
onFocus={() => navigation.navigate('Search')}
iconContent={
<Icon
size={16}
color={theme.COLORS.MUTED}
name="magnifying-glass"
family="entypo"
/>
}
/>
);
};
renderOptions = () => {
const { navigation, optionLeft, optionRight } = this.props;
return (
<Block row style={styles.tabs}>
<Button
shadowless
style={[styles.tab, styles.divider]}
onPress={() => navigation.navigate('Categories')}
>
<Block row middle>
<Icon name="globe" family="feather" style={{ paddingRight: 8 }} />
<Text size={16} style={styles.tabTitle}>
{optionLeft || 'Locations'}
</Text>
</Block>
</Button>
<Button
shadowless
style={styles.tab}
onPress={() => navigation.navigate('Deals')}
>
<Block row middle>
<Icon name="grid" family="feather" style={{ paddingRight: 8 }} />
<Text size={16} style={styles.tabTitle}>
{optionRight || 'Categories'}
</Text>
</Block>
</Button>
</Block>
);
};
renderTabs = () => {
const { tabs, tabIndex, navigation } = this.props;
const defaultTab = tabs && tabs[0] && tabs[0].id;
if (!tabs) return null;
return (
<Tabs
data={tabs || []}
initialIndex={tabIndex || defaultTab}
onChange={(id) => navigation.setParams({ tabId: id })}
/>
);
};
renderHeader = () => {
const { search, tabs, options } = this.props;
if (search || tabs || options) {
return (
<Block center>
{search ? this.renderSearch() : null}
{options ? this.renderOptions() : null}
{tabs ? this.renderTabs() : null}
</Block>
);
}
return null;
};
addInstaPost = () => {
this.setState({ modalVisible: true });
};
render() {
const { back, title, white, transparent, navigation, scene } = this.props;
const noShadow = ['Profile'].includes(title);
const noShadowWhite = ['Search'].includes(title);
const headerStyles = [
!noShadow ? styles.shadow : null,
transparent ? { backgroundColor: 'rgba(0,0,0,0)' } : null,
];
var myHeaderStyle = styles.shadow;
if (noShadow) {
var myHeaderStyle = '';
} else if (transparent) {
var myHeaderStyle = "{ backgroundColor: 'rgba(0,0,0,0)' }";
} else if (noShadowWhite) {
var myHeaderStyle = styles.searchShadow;
}
return (
<Block style={myHeaderStyle}>
<View style={styles.imageContainer} transparent={transparent}>
{
this.renderInstaPostButton()
}
</View>
<View style={styles.item}>
<NavBar
back={back}
title={title}
style={styles.navbar}
transparent={transparent}
right={this.renderRight()}
rightStyle={{ alignItems: 'center' }}
leftStyle={{ paddingTop: 3, flex: 0.3 }}
leftIconName={back ? 'leftcircle' : 'menu-fold'}
leftIconFamily="AntDesign"
leftIconSize="1.6"
leftIconColor={
white ? materialTheme.COLORS.NAVICON : theme.COLORS.ICON
}
titleStyle={[
styles.title,
{ color: theme.COLORS[white ? 'WHITE' : 'ICON'] },
]}
onLeftPress={this.handleLeftPress}
/>
</View>
{this.renderHeader()}
</Block>
);
}
}
So basically inside BasketButton2 I am trying to make a call to a function which is inside the class Header.
onPress={() => Header.addInstaPost() is not working
as well as onPress={() => this.addInstaPost()
I am getting Header.addInstaPost is not defined.
How I can refer to function inside class?
Thanks!!
You can pass addInstaPost as a property to BasketButton2
class Header extends React.Component {
addInstaPost = () => {
this.setState({ modalVisible: true });
};
renderRight = () => {
const { white, title, navigation, scene } = this.props;
if (global.loggedUser === true) {
return [
<BasketButton2
key="basket-search"
navigation={navigation}
isWhite={white}
onPress={this.addInstaPost}
/>,
<ChatButton
key="chat-search"
navigation={navigation}
isWhite={white}
/>,
];
} else {
return [
<BasketButton
key="basket-search"
navigation={navigation}
isWhite={white}
/>,
<ChatButton
key="chat-search"
navigation={navigation}
isWhite={white}
/>,
];
}
};
}
const BasketButton2 = ({ isWhite, style, navigation, onPress }) => (
<TouchableOpacity
style={[styles.button, style]}
onPress={onPress}
>
<Icon
family="Entypo"
size={16}
name="new-message"
color={theme.COLORS[isWhite ? 'WHITE' : 'ICON']}
/>
</TouchableOpacity>
);
IMO this is the most prefered way for such case

AsyncStorage mapping not working

I have code
AsyncStorage.getItem("Friends").then((value) => {
this.setState({"Friends": value});
}).done();
I am trying to show in list using
render() {
return ({
this.state.Friends.map((o,i) => {
<View key={i} style={styles.row}>
<View>
<Text style={styles.app_type_name}>{o.name}</Text>
</View>
</View>
})
})
}
I am getting
error evaluating object 'this.state.Friends'
You render method should looks like :
render() {
const {Friends} = this.state;
return (
<div>
{
Friends && Friends.map((o,i) =>
<View key={i} style={styles.row}>
<View><Text style={styles.app_type_name}>{o.name}</Text></View>
</View>
)
}
</div>
);
}

undefined is not an object(evaluating 'this.onSubmitPressed.bind')

I have a listview that shows data through Json. I introduced a function and while clicking on every Row, That shows an Alert including {shop_name}.
But at first step it dosen't recognise the Function.
Function is in the same class
When I put Alert in the onPress, it works
class SearchPage extends Component {
constructor(props) {
super(props);
var dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.ruid != r2.guid});
this.state = {
id: 'SearchPage',
shopid: this.props.shopid,
homesearchinpt: this.props.homesearchinpt,
dataSource: dataSource.cloneWithRows(shopsArray),
isLoading: true
};
}
componentDidMount(){
this.fetchData();
}
onSubmitPressed(){
Alert.alert(
'Alert Title',
'alertMessage',
)
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
})
.done();
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderShops}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>Loading</Text>
</View>
);
}
renderShops(shop) {
return (
<View style={styles.container} >
<TouchableOpacity onPress={this.onSubmitPressed.bind(this)}>
<Image
source={{uri: shop.shop_logo}}
style={{width: 50, height: 50}}>
</Image>
<View>
<Text style={styles.shop_name}>{shop.shop_name}</Text>
<Text style={styles.shop_description}>{shop.shop_description}</Text>
</View>
</TouchableOpacity>
</View>
);
}
};
Error:
undefined is not an object(evaluating 'this.onSubmitPressed.bind')
onSubmitPressed(shopName) {
Alert.alert(
'Alert Title',
shopName,
)
}
<TouchableOpacity onPress={() => this.onSubmitPressed(shop.shop_name)}>
I rewrote the Codes and the problem solved.
Thanks

How to relate react native ToolbarAndroid with Navigator

I would like to know a way to relate ToolbarAndroid with the Navigator component. My intention is always to show the route.title in a ToolbarAndroid child, such as a Text component. This way, if a use the BackAndroid component, my title is always up to date! I don't want to use Navigator.NavigationBar because I would miss the overflow menu built in on the ToolbarAndroid.
Appreciate any help.
Here is my code:
//... some code before
render() {
return(
<DrawerLayoutAndroid
drawerWidth={300}
ref={(drawerElement) => { this.DRAWER = drawerElement; }}
drawerPosition={DrawerLayoutAndroid.positions.left}
onDrawerOpen={this.setDrawerState}
onDrawerClose={this.setDrawerState}
renderNavigationView={() => <DrawerMenu navigate={this.navigateTo} />}
>
<Icon.ToolbarAndroid
titleColor='#fff'
navIconName='md-menu'
onIconClicked={this.toggleDrawer}
actions={toolbarActions}
onActionSelected={this._onActionSelected}
style={styles.appBar}
overflowIconName="md-more"
>
<View>
<TouchableOpacity
onPress={this.navigateTo.bind(this, 0)}
style={styles.appBarLogo}
>
<Icon name="md-boat" size={30} color="#fff" />
<Text
style={styles.appBarTitle}
numberOfLines={1}
>
{this.state.title}
</Text>
</TouchableOpacity>
</View>
</Icon.ToolbarAndroid>
<Navigator
initialRoute={routes[0]}
renderScene={(route, navigator) => {
switch (route.index) {
case 0:
return <Home />
case 1:
return <Lindau />;
case 2:
return <About />;
case 3:
return <Credits />;
default:
return <Home />;
}
}}
configureScene={(route, routeStack) =>
Navigator.SceneConfigs.FloatFromRight
}
ref={(nav) => { this._navigator = nav; }}
/>
</DrawerLayoutAndroid>
);
}
So, please, help me if anyone has a better solution for this. After several attempts, I figured out one possible solution.
I created a state for my component called 'routes', then, I've set up my Toolbar title with this state. Basically, this state is a stack of my routes. When I change my scene, I push this route in my state, when I back from BackAndroid component, I pop out the route from the state, and everything works fine.
Here the code fixed:
class App extends Component {
constructor(props) {
super(props);
this.state = {
routes: [0], // Here the state to fix the problem...
drawerClosed: true,
}
this.toggleDrawer = this.toggleDrawer.bind(this);
this._onActionSelected = this._onActionSelected.bind(this);
this.navigateTo = this.navigateTo.bind(this);
this.setDrawerState = this.setDrawerState.bind(this);
this.handlesBackButton = this.handlesBackButton.bind(this);
}
navigateTo(idx) {
this.setState({
routes: [ ...this.state.routes, idx]
});
this.DRAWER.closeDrawer();
if (idx === 0) {
this._navigator.resetTo(routes[0]);
this.setState({
routes: [0]
});
} else {
this._navigator.push(routes[idx]);
}
}
handlesBackButton() {
if (this._navigator && this._navigator.getCurrentRoutes().length > 1) {
try {
this._navigator.jumpBack();
const _routes = this.state.routes.slice();
_routes.pop();
this.setState({
routes: _routes
});
} catch(e) {}
return true;
}
return false;
}
render() {
return(
<DrawerLayoutAndroid
drawerWidth={300}
ref={(drawerElement) => { this.DRAWER = drawerElement; }}
drawerPosition={DrawerLayoutAndroid.positions.left}
onDrawerOpen={this.setDrawerState}
onDrawerClose={this.setDrawerState}
renderNavigationView={() => <DrawerMenu navigate={this.navigateTo} />}
>
<Icon.ToolbarAndroid
titleColor='#fff'
navIconName='md-menu'
onIconClicked={this.toggleDrawer}
actions={toolbarActions}
onActionSelected={this._onActionSelected}
style={styles.appBar}
overflowIconName="md-more"
>
<View style={styles.appBarLogo}> // I have to fix this component view...
<TouchableOpacity
onPress={this.navigateTo.bind(this, 0)}
>
<Icon name="md-boat" size={30} color="#fff" />
</TouchableOpacity>
<Text
style={styles.appBarTitle}
numberOfLines={1}
>
{routes[this.state.routes[this.state.routes.length - 1]].title}
</Text>
</View>
</Icon.ToolbarAndroid>
<Navigator
initialRoute={routes[0]}
renderScene={(route, navigator) => {
switch (route.index) {
case 0:
return <Home />;
case 1:
return <Lindau />;
case 2:
return <About />;
case 3:
return <Credits />;
default:
return <Home />;
}
}}
configureScene={(route, routeStack) =>
Navigator.SceneConfigs.FloatFromRight
}
ref={(nav) => { this._navigator = nav; }}
/>
</DrawerLayoutAndroid>
);
}
}