Using the Onsen playground & React Combining Navigator and Tabbar example, I made this - https://media.giphy.com/media/fjxPFluObAs5P3cXms/giphy.gif
I wanted to change the position of the button and input field for where you add more users, so I used a fab. Whenever I call the navigator.pushPage it says TypeError: navigator.pushPage is not a function.
The code behind it is:
fabHandleClick() {
navigator.pushPage({ component: ItemForm, props: { key: 'itemForm' } });
}
render() {
return (
<Page>
<List
dataSource={this.props.users}
renderRow={this.renderList.bind(this, this.props.users, this.props.added, "Add", true)}
/>
<br />
<hr />
<br />
<List
dataSource={this.props.added}
renderRow={this.renderList.bind(this, this.props.added, this.props.users, "Remove", false)}
/>
<Fab
onClick={this.fabHandleClick}
position='bottom right'>
<Icon icon='md-face' />
</Fab>
</Page>
);
}
Thanks in advance!
<Page /> should have access to the navigator object either by being wraped in a function or as a prop
Wrapped example:
renderPage = (route, navigator) => (<Ons.Page key={route.title} renderToolbar={() => this.renderToolbar(route, navigator)}>
<section style={{ margin: '16px', textAlign: 'center' }}>
<Ons.Button onClick={() => this.fabHandleClick(navigator)}>
Push Page
</Ons.Button>
</section>
</Ons.Page>);
fabHandleClick(navigator) {
navigator.pushPage({ component: ItemForm, props: { key: 'itemForm' } });
}
Related
I have this icon that needs to run a function onLogout in a separate file
First I tried passing navigation param to bottomTab options like so
<BottomTab.Screen
name="Settings"
component={Settings}
options={(navigation) => ({
title: "Settings",
tabBarIcon: () => <Icon name="settings" size={20} color="black" />,
headerRight: (
<Icon
onPress={navigation.getParam('onLogout')}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
})}
/>
In the settings screen where the function lives I have initialized the function like so
this.props.navigation.setParams({ onLogout: this.onLogout });
I have tried inside componentDidMount and componentWillMount
Also tried to bind it
constructor(props) {
super(props);
this.onLogout = this.onLogout.bind(this);
}
TypeError: navigation.getParam is not a function. (In
'navigation.getParam('onLogout')', 'navigation.getParam' is undefined)
At one point the function get executed but without me touching the icon but I changed to this
this.props.navigation.setParams({ onLogout: this.onLogout() });
Since that didn't work I tried writing the options in the file itself
export default class Settings extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerRight: (
<Icon
// onPress={navigation.getParam('onLogout')}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
};
};
...
No icon shows up on the screen and nothing works with that method (title, ect...)
Try this :
<BottomTab.Screen
name="Settings"
component={Settings}
options={(props) => ({
title: "Settings",
tabBarIcon: () => <Icon name="settings" size={20} color="black" />,
headerRight:() =>(
<Icon
onPress={()=>props.route.params.onLogout()}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
})}
/>
I wrote below code to make multiple side menus but it occurred error
Another navigator is already registered for this container. You likely have multiple navigators under a single "NavigationContainer" or "Screen". Make sure each navigator is under a separate "Screen" container.
However I've tried to find the Container for multiple drawers but no luck.
What should I do?
Thanks in advance.
import React from 'react';
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
import { Ionicons } from '#expo/vector-icons';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationNativeContainer } from '#react-navigation/native';
import { Container, Text, Button } from 'native-base';
import 'react-native-gesture-handler'
function BlankScreen({ navigation }) {
return (
<Text>Blank</Text>
);
}
function HomeScreen({ navigation }) {
return (
<Container style={{ flex: 1, flexDirection: 'column-reverse' }}>
<Button onPress={() => navigation.navigate('Menu')}>
<Text>Go to Menu</Text>
</Button>
<Button onPress={() => navigation.navigate('Favorit')}>
<Text>Go to Favorit</Text>
</Button>
</Container>
);
}
function MenuScreen({ navigation }) {
return (
<Container style={{ flex: 1, flexDirection: 'column-reverse' }}>
<Button onPress={() => navigation.goBack()}>
<Text>Go back home</Text>
</Button>
</Container>
);
}
function FavoritScreen({ navigation }) {
return (
<Container style={{ flex: 1, flexDirection: 'column-inverse' }}>
<Button onPress={() => navigation.goBack()}>
<Text>Go back home</Text>
</Button>
</Container>
);
}
const DrawerL = createDrawerNavigator();
const DrawerR = createDrawerNavigator();
export default function App() {
return (
<Container>
<NavigationNativeContainer>
<DrawerL.Navigator initialRouteName="Home" drawerPosition="left">
<DrawerL.Screen name="Home" component={HomeScreen} />
<DrawerL.Screen name="Menu" component={MenuScreen} />
<DrawerL.Screen name="Favorit" component={FavoritScreen} />
</DrawerL.Navigator>
<DrawerR.Navigator initialRouteName="Blank" drawerPosition="right">
<DrawerR.Screen name="Blank" component={BlankScreen} />
<DrawerR.Screen name="Menu" component={MenuScreen} />
<DrawerR.Screen name="Favorit" component={FavoritScreen} />
</DrawerR.Navigator>
</NavigationNativeContainer>
</Container>
);
The way you wrote it won't work, because consider this: you've 2 drawers, one has initial route as "Home", and other as "Blank". Which one should be rendered?
Here, you need to follow the same approach as React Navigation 4, put one drawer inside another:
function HomeStack() {
return (
<Stack.Navigator screenOptions={{ animationEnabled: false }}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Menu" component={MenuScreen} />
<Stack.Screen name="Favorit" component={FavoritScreen} />
</Stack.Navigator>
)
}
function RightDrawer() {
return (
<DrawerR.Navigator initialRouteName="Home" drawerPosition="right">
<DrawerR.Screen name="Home" component={HomeStack} />
<DrawerR.Screen name="Menu" component={MenuScreen} />
<DrawerR.Screen name="Favorit" component={FavoritScreen} />
</DrawerR.Navigator>
)
}
function LeftDrawer() {
return (
<DrawerL.Navigator initialRouteName="RightDrawer" drawerPosition="left">
<DrawerL.Screen name="RightDrawer" component={RightDrawer} />
</DrawerL.Navigator>
);
}
function App() {
return (
<NavigationNativeContainer>
<LeftDrawer />
</NavigationNativeContainer>
)
}
Since your left drawer won't show the screens that you have in Stack, you will need to provide a custom component for your drawer which lists the screens: https://reactnavigation.org/docs/en/next/drawer-navigator.html#providing-a-custom-drawercontent
<Search
ref="search_box"
onSearch={this.onSearch}
backgroundColor="white"
cancelButtonTextStyle={{ color: "red" }}
placeholder="Search Food..."
placeholderCollapsedMargin={wp("40%")}
placeholderExpandedMargin={wp("7%")}
searchIconCollapsedMargin={wp("45%")}
inputHeight={hp("4%")}
/>
<List>
<ListItem>
<Text>Milk</Text>
</ListItem>
<ListItem>
<Text>Chicken</Text>
</ListItem>
<ListItem>
<Text>Rice</Text>
</ListItem>
Hey everyone, I am using React Native with a class component and I was wondering how can I hide the list, and show it only when I tap on the search bar?
You can defined a boolean variable and set it true when search text input focused,
like that
...
this.state = {
showList: false,
}
...
return (
<View>
<SearchBar
...
onFocus={() => setState({showList: true})}
/>
{this.state.showList && (
<FlatList
...
/>
)}
</View>
)
here I supposed search component inherits the TextInput properties.
In header I add left component - icon, and I want to set icon on click. How can I do that?
I tried to set state value and return component that depends from this value.
<Header
placement="left"
leftComponent={
<Icon
name='keyboard-arrow-left'
color='#ffffff'
size={40}
onPress={}
/>
}
centerComponent={<Text>User Info</Text>}
/>
You can create separate component for icon
export class MyIcon extends Component {
state = { name: 'keyboard-arrow-left' }
render() {
return (
<Icon
name={this.state.name}
color='#ffffff'
size={40}
onPress={() => this.setState({ name: 'close' })}
/>
);
}
}
and use this component for leftComponent of your Header
<Header
placement="left"
leftComponent={
<MyIcon/>
}
centerComponent={<Text>User Info</Text>}
/>
The simplest way to fix this issue is to add a reference to your Icon component. Then use that reference to change any of the props of your icon.
constructor(props){
super(props);
this.state = {};
this.myIcon = '';
}
updateIconName = (nameEntered) => {
this.myIcon.name = nameEntered;
}
render() {
return(
<View style={{flex: 1}}>
<Header
placement="left"
leftComponent={
<Icon
name='keyboard-arrow-left'
color='#ffffff'
size={40}
onPress={this.updateIconName}
ref={(element) => {this.myIcon = element;}}
/>
}
centerComponent={<Text>User Info</Text>}
/>
</View>
);
}
I'm calling data from this API https://api.themoviedb.org/3/discover/movie?api_key=9a4a662a126525b07d4b84b079d809d8&language=en-US&sort_by=popularity.asc&include_adult=false&include_video=false&page=1
and fetching the url, so I can get which data to display in mobile device, the problem is the in native-base library, List Component is deprecated so, the documentation say should use Flatlist Component from official react-native, and here the code :
// render data list
renderDataMovieList = ({ movieItem }) => {
return(
<ListItem Thumbnail>
<Left>
<Thumbnail square large source= {{ uri:"https://image.tmdb.org/t/p/w500" + movieItem.poster_path }}/>
<Body>
<Text>{ movieItem.title }</Text>
<Text note >Release Date : { movieItem.release_date }</Text>
<Text note >Vote Avarage : { movieItem.vote_average }</Text>
<Text note >Language : { movieItem.original_language}</Text>
</Body>
</Left>
<Button transparent>
<Icon name="arrow-forward" style={{ color: "#999" }}/>
</Button>
</ListItem>
);
}
render(){
return(
<Container>
<Header>
<Left>
<Button transparent>
<Icon name="menu" />
</Button>
</Left>
<Body>
<Title>Movie List</Title>
</Body>
<Right />
</Header>
<Content>
<FlatList
data = { this.state.data }
renderItem = { this.renderDataMovieList}
keyExtractor={ movieItem => movieItem.id }
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
initialNumToRender={5}
/>
</Content>
</Container>
);
}
But after I ran that code, I get this error
TypeError: undefined is not an object (evaluating 'movieItem.poster_path')
I was following this code pattern : http://docs.nativebase.io/docs/examples/FlatListExample.html
but I still get the error.
I am assuming movieItem is undefined(that is why the error).
Ideally, you should wait till movies call is completed and then call the component and also you are not passing movieItem data to renderDataMovieList method.
Assuming movieItem is the data you are waiting for.
{ movieItem &&
<FlatList
data = { this.state.data }
renderItem = { this.renderDataMovieList({ movieItem: movieItem }) }
keyExtractor={ movieItem => movieItem.id }
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
initialNumToRender={5}
/>
}