I am building an app that has a list on the home screen routing to a number of other screens.
I created a list component that is rendered on the home page, and therefore, need to pass the navigation down to the list component. The list component, in turn, will determine which screen to display depending on which item is pressed.
I am using a Stack Navigator on my router.js file
export const HomeStack = StackNavigator({
Home: {
screen: Home,
navigationOptions: {
title: 'Home',
},
},
Nutrition: {
screen: Nutrition,
navigationOptions: {
title: 'Nutrition',
}
},
});
In my home.js screen I have the below code inside the render method
render() {
return (
<View>
<View>
<ListComponent navigate={this.props.navigation.navigate('')} />
<Button
title="Go to Nutrition"
onPress={() => this.props.navigation.navigate('Nutrition')}
/>
</View>
</View>
);
}
The Button successfully routes to the Nutrition.js screen.
But, I try to get my ListComponent.js to handle where to route as this file maps through my list array.
render() {
return (
<List>
{ListData.map((listItem, i) => (
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={this.onPressHandler(listItem.title)}
/>
))}
</List>
);
}
How can I properly pass the navigation as props down to ListComponent.js and then use the title from the list array to determine which screen to display?
change this line :
<ListComponent navigate={this.props.navigation.navigate('')} />
to this :
<ListComponent navigate={(screen)=>this.props.navigation.navigate(screen)}/>
and change this
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={this.onPressHandler(listItem.title)}
/>
to this :-
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={()=>this.props.navigate(listItem.title)}
/>
As you are calling the method directly not binding it to the component.
I am assuming that your code in ListItem.js is correct.
Related
In my react application, I have added a sidebar window for the mobile view. Inside the sidebar, I have few links that navigates to certain pages like contact-us, about-us, etc. accordingly.
It looks like this:
As per my requirement, when clicking on any of the links, the sidebar state sets to false, causing the sidebar to be closed and rendering the page navigated using the link.
But I am facing issues such that whenever I click any of the links below, the page related to that link renders (i.e. it navigates to the page in the background), but the sidebar does not close, even though its state is updated every time as required. The sidebar remains open.
This is the code snippet:
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
const SideDrawer = () => {
const navigate = useNavigate();
const [openDrawer, setOpenDrawer] = useState(false);
const [usefulLinks] = useState([
{
link_name: "About Us",
path: "/about-us",
},
{
link_name: "Contact Us",
path: "/contact-us",
},
{
link_name: "Privacy Policy",
path: "/privacy-policy",
},
{
link_name: "Terms and Conditions",
path: "/terms-and-conditions",
},
]);
const handleSideBar = (e, path) => {
e.preventDefault();
setOpenDrawer(false);
navigate(`${path}`);
};
return (
<>
<Drawer open={openDrawer} onClose={() => setOpenDrawer(false)}>
<Grid container direction="column" style={{ flexGrow: 1 }}>
<Grid
item
style={{
marginTop: "auto",
}}>
<List>
{usefulLinks.map(({ path, link_name }, id) => {
return (
<ListItem key={id} onClick={(e) => handleSideBar(e, path)}>
{link_name}
</ListItem>
);
})}
</List>
</Grid>
</Grid>
</Drawer>
<IconButton
onClick={() => setOpenDrawer(!openDrawer)}
className={classes.icon}>
<MenuIcon fontSize="large" />
</IconButton>
</>
);
}
export default SideDrawer;
I am using MUI's List for element rendering.
There might be a minor issue that I'm unable to figure out, any help to resolve the same will be appreciated!
Thanks in advance.
I am new with react native, and I am trying to make the once a carousel component card is pressed, it should navegate to other page and send the respective id from the card array.
this is my '.App.js' page and it works properly:
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name='Receita' component={selectType} />
<Stack.Screen name='Informe os ingredientes' component={findRecipe} />
</Stack.Navigator>
</NavigationContainer>
);
}
this is the carousel array:
const carouselItems = [
{
id: 1,
title: "Doce",
text: "[TEXTO DESCRITIVO]",
illustration: require('../../assets/sobremesa.jpg'),
},
{
id: 2,
title: "Salgado",
text: "[DESCRIÇÃO]",
illustration: require('../../assets/refeicao.jpg'),
},
]
and this one is the Carousel component that I would like to update and once it is pressed, it should send the user to the 'findRecipe' page
return (
<View style={styles.container} >
<TouchableOpacity onPress={goForward}>
<Text style={styles.titleText}>Selecione o tipo de receita</Text>
</TouchableOpacity>
<Carousel
layout={"default"}
ref={ref => carousel = ref}
data={carouselItems}
sliderWidth={screenWidth}
sliderHeight={screenWidth}
itemWidth={screenWidth - 60}
renderItem={renderItem}
onSnapToItem={index => setState({ activeIndex: index })}
hasParallaxImages={true}
/>
<Button title='INGREDIENTES' onPress={() => navigation.navigate('Informe os ingredientes')}></Button>
</View >
);
I got a way to do it in a Button component, but I really need to do it on the Carousel card and send the id of the respective register that was pressed.
Can anyone help on it?
The example send is working, thanks a lot Tuan!
snack.expo.io/KJl_IKU3D – tuan.tran 29 mins ago
I have a case where a feature contains a FlatList full of information, a search bar, sort button, and filter button.
For the sort and filter buttons I need to pull up a modal from the bottom that takes up half the screen.
I understand that React Navigation wants us to only create one 'root' navigator and all other navigators be dependents; however, in this particular case I would very much like to explicitly add a navigator to this page where a user presses on the filter button, brings up the modal, presses a filter option and then have the modal navigate to another filter subpage within the confines of its view, while maintaining the main page content and root navigation state in the background.
I remember implementing this in React Navigation V1.x, but does anyone know how to get around this in V2.x?
Rather than doing it with nested stack navigator and things, I've implemented your requirement using built-in react native modal.
App
import React, { Component } from 'react';
import { createStackNavigator } from 'react-navigation';
import { MainScreen } from './src/screens/MainScreen';
const RootStack = createStackNavigator(
{
MainScreen
},
{
navigationOptions: {
header: null
}
}
);
export default class App extends Component {
render() {
return (
<RootStack />
);
}
}
MainScreen
import { default as React, PureComponent } from 'react';
import { View, Text, Button, Alert, Modal } from 'react-native';
interface Props {
}
interface States {
num: number;
isFilterOneVisible: boolean;
isFilterTwoVisible: boolean;
}
export class MainScreen extends PureComponent<Props, States> {
state = {
num: 0,
isFilterOneVisible: false,
isFilterTwoVisible: false
}
render() {
return (
<View
flex={1}
justifyContent={'space-evenly'}
alignItems={'center'}
>
<Text style={{ fontSize: 50 }}>{this.state.num}</Text>
<Button
title={'CHANGE STATE'}
onPress={() => {
this.setState((prevState: States) => ({
num: prevState.num + 1
}));
}}
/>
{/* Search */}
<Button
title={'Search'}
onPress={() => {
Alert.alert('Search', 'Search clicked');
}}
/>
{/* Sort*/}
<Button
title={'Sort'}
onPress={() => {
Alert.alert('Sort Clicked', 'Sort clicked')
}}
/>
<Button
title={'Filter'}
onPress={() => {
this.setState({
isFilterOneVisible: true
})
}}
/>
{/* Filter Modal 1*/}
<Modal
visible={this.state.isFilterOneVisible}
transparent={true}
animationType={'slide'}
onRequestClose={() => {
this.setState({
isFilterOneVisible: false
})
}}
>
<View
flex={1}
justifyContent={'flex-end'}
backgroundColor={'rgba(0,0,0,0.2)'}
>
{/* Bottom */}
<View
justifyContent={'center'}
alignItems={'center'}
backgroundColor={'white'}
height={200}
>
<Button
title={'GO TO NEXT FILTER STATE'}
onPress={() => {
this.setState({
isFilterOneVisible: false,
isFilterTwoVisible: true
})
}}
/>
</View>
</View>
</Modal>
{/* Filter Modal Two */}
<Modal
visible={this.state.isFilterTwoVisible}
transparent={true}
animationType={'slide'}
onRequestClose={() => {
this.setState({
isFilterTwoVisible: false
})
}}
>
<View
flex={1}
justifyContent={'flex-end'}
backgroundColor={'rgba(0,0,0,0.2)'}
>
{/* Bottom */}
<View
justifyContent={'center'}
alignItems={'center'}
backgroundColor={'white'}
height={200}
>
<Button
title={'SET DATA AS 1000'}
onPress={() => {
this.setState({
isFilterTwoVisible: false,
num: 1000
})
}}
/>
</View>
</View>
</Modal>
</ View >
);
}
}
NOTE: The code is not optimised and follows some bad patterns like arrow-methods-in-jsx. This is just a suggestion with a working example. Feel free to enhance the code and follow the divide-and-conquer strategy ;) . The full source code can be found from here
In react navigation drawermenu. I want to display the username 'John Doe' which is in the state of my main component 'Router' How can I pass it the CustomDrawerContentComponent.
Extra Info: I'm getting this name from AsyncStorage in
componentDidMount
This is my code
export default class Router extends Component {
constructor(props) {
super(props);
this.state = {
employeeName: "John Doe" //<-----How to pass this name to CustomDrawerContentComponent????
};
}
render() {
return <MyApp />;
}
}
const MyApp = DrawerNavigator(
{
Home: {
screen: Home
},
History: {
screen: History
},
AddDetails: {
screen: AddDetails
}
},
{
initialRouteName: "Home",
drawerPosition: "left",
contentComponent: CustomDrawerContentComponent,
drawerOpenRoute: "DrawerOpen",
drawerCloseRoute: "DrawerClose",
drawerToggleRoute: "DrawerToggle",
contentOptions: {
activeTintColor: "#EF4036"
}
}
);
const CustomDrawerContentComponent = props => (
<Container>
<Header style={styles.drawerHeader}>
<Body style={styles.container}>
<Image
style={styles.drawerImage}
source={{
uri: "http://themes.themewaves.com/nuzi/wp-content/uploads/sites/4/2013/05/Team-Member-3.jpg"
}}
/>
<Text style={styles.drawerText}>**How get the name here?**</Text>
</Body>
</Header>
<Content>
<DrawerItems {...props} />
</Content>
</Container>
);
You can use screenProps:
<MyApp
screenProps={{employeeName: this.state.employeeName}}
/>
And then use it in your custom contentComponent:
contentComponent:(props)=>(
<View>
<Text>{props.screenProps.employeeName}</Text>
<DrawerItems {...props} />
</View>
)
This is the answer for your question. But first of all I don't recommend using your top level component for such business logic. Use it only for navigation.
And see my answer here: Customizing Drawer
I recommend you to create a Redux connected custom drawer as I describe in my answer. If you don't know how to use Redux, I definitely recommend you to learn it. You will need it as your application grows.
Just pass as screenprops
Render(){
return <Myapp screenprops={employeename:this.state.employeeName}/>;
}
You can access it from drawer like this this.props.screenprops.employeename
I have a component that renders a Navigator :
render() {
return (
<View style={{flex: 1}}>
<Navigator
style={{backgroundColor: '#31BC72'}}
initialRoute={Home.route()}
renderScene={(route, navigator) => {
return React.createElement(route.component, _.extend({navigator: navigator}, route.passProps));
}}
configureScene={() => {
return {
...Navigator.SceneConfigs.FadeAndroid,
defaultTransitionVelocity: 10000,
gestures: {}
};
}} />
</View>
);
}
That's what it looks like :
When I push a new route, let's say from the Home component, it looks like this :
I'd like to have on this component only a navigation bar with only the back button. I can't figure how to do that..