Drawer Navigator Children Props - react-native

Is there a way for me to get the props from a child of my DrawerNavigator inside my CustomDrawerComponent ?
When I open my Drawer, I wanted to get my StackNavigator screens inside it, not simply "AppStackNavigator". Is there a easy way do do that ?
My Navigators:
const AppStackNavigator = createStackNavigator(
{
Início: {
screen: HomeScreen
},
Perfil: {
screen: ProfileScreen
},
Notificações: {
screen: NotificationScreen
},
'Criar Evento': {
screen: CreateEventScreen
},
EventScreen
},
StackNavigatorConfig()
)
const AppNavigator = createDrawerNavigator(
{
AppStackNavigator
},
{
contentComponent: Drawer,
drawerBackgroundColor: color.primary.main
}
)
const AppContainer = createAppContainer(AppNavigator)
My CustomDrawerContentComponent:
export default (CustomDrawerContentComponent = props => {
return (
<ScrollView>
<TouchableOpacity onPress={() => props.navigation.closeDrawer()} style={styles.close}>
<EvilIcons style={{ color: color.primary.contrastLightText }} size={40} name="close" />
</TouchableOpacity>
<View style={styles.thumbImageContainer}>
<ThumbImage image={require('../assets/images/user.jpg')} />
<View style={styles.statusContainer}>
<TextApp>Luis Coimbra</TextApp>
<TextApp secondary>Apaixonado por Jesus</TextApp>
</View>
</View>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} {...itemsStyle} />
</SafeAreaView>
</ScrollView>
)
})

With the props.navigation.state.routes[0].routes.slice(-1)[0].routeName, I can manage to get the active router so I am able to style. If you have a better way, I'd be glad to read.
Not exactly what I was expecting, but it works well for now:
export default (CustomDrawerContentComponent = props => {
const activeRouterName = props.navigation.state.routes[0].routes.slice(-1)[0].routeName
return (
<ScrollView>
<TouchableOpacity onPress={() => props.navigation.closeDrawer()} style={styles.close}>
<EvilIcons style={{ color: color.dark.contrast }} size={40} name="close" />
</TouchableOpacity>
<View style={styles.thumbImageContainer}>
<ThumbImage source={require('../assets/images/user.jpg')} />
<View style={styles.statusContainer}>
<TextApp dark>Luis Coimbra</TextApp>
<TextApp secondary>Apaixonado por Jesus</TextApp>
</View>
</View>
<SafeAreaView
style={{ flex: 1, borderTopWidth: 2, borderTopColor: color.dark.contrast }}
forceInset={{ top: 'always', horizontal: 'never' }}
>
{['Início', 'Perfil', 'Notificações', 'Criar Evento'].map(routerName => (
<View key={routerName} style={routerName == activeRouterName && styles.activeView}>
<TextApp
onPress={() => props.navigation.navigate(routerName)}
style={{
color:
routerName == activeRouterName
? color.secondary()
: color.dark.contrast,
margin: 16,
fontWeight: 'bold'
}}
>
{routerName}
</TextApp>
</View>
))}
</SafeAreaView>
</ScrollView>
)
})
Result:

Related

React Native: How can I put a pop-up Modal into flatlist

I've made a flatlist with a few data inside. I want to make a pop-up information for each item in the flatlist. So I tried putting Modal into the renderItem function but when it sets the modal state visible, it will show all of the information in my flatlist. I think it should be setting the modal visible state by id or something like that but I don't know how to do it. Any suggestion?
my renderItem:
function RenderItem({ item }) {
return (
<View>
<Modal
animationType='slide'
transparent={true}
visible={infoModal}>
<View style={styles.informationContainer}>
<View style={styles.informationBox}>
<Text>{item.file.displayName}</Text>
<Button title=' OK ' onPress={() => setInfoModal(false)} />
</View>
</View>
</Modal>
<TouchableOpacity style={styles.listBox} onPress={() => setInfoModal(true)}>
<View>
<Text numberOfLines={1} style={styles.listText}>{item.file.displayName}</Text>
<Text style={{ width: 200, color: 'rgba(0, 0, 0, 0.5)' }}>{item.certificateName}</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
<TouchableOpacity>
<Icon name='search' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
<TouchableOpacity onPress={() => handleDownload(item)}>
<Icon name='download' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
</View>
</TouchableOpacity>
</View>
)
}
Instead of setting a simple boolean value about whether the Modal should appear, you can set some sort of identifiable value that tells it what item to load (and otherwise leave it undefined).
Bare-bones example:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
export default function App() {
const [modalInfo, setModalInfo] = React.useState(undefined);
const renderItem = ({ item }) => (
<TouchableOpacity onPress={() => setModalInfo(item.title)}><Text>{item.title}</Text></TouchableOpacity>
);
return (
<View style={styles.container}>
<Modal visible={modalInfo !== undefined}>
<View style={[{borderWidth: 1},styles.centeredView]}>
<Text>{modalInfo}</Text>
<TouchableOpacity onPress={() => setModalInfo(undefined)}><Text>Close</Text></TouchableOpacity>
</View>
</Modal>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

componentWillReceiveProps not triggering from child screen inside Tabview

I'm new in React native here. I got stuck on this scenario. I have a Dashboard screen. Inside dashboard screen, there's Hitcher screen that has Tabview. And there are HitcherTrip and HitcherChat inside the Tabview. In HitcherTrip, i expected componentWillReceiveProps() will trigger after calling Actions.goToOtherLayout() but componentWillReceiveProps() is triggered on Dashboard screen (Parent screen).
Dashboard
const Menu = createDrawerNavigator(
{
First: { screen: Hitcher },
Second: { screen: Driver }
},
{
contentComponent: props => (
<ScrollView>
<View style={{ padding:20, backgroundColor:'#4ca858' }}>
<Image source={require('../assets/pp.png')} style={{ borderRadius: 40, borderWidth: 1, borderColor: '#fff',width:80, height: 80 }} />
<CustomDrawerText/>
</View>
<SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
<Drawer.Item
label="I am Hitcher"
style={styles.drawerItem}
onPress={
() => {}
}
/>
<View style={{ height:1, backgroundColor:'#a8a8a8', marginLeft: 15, marginRight: 15 }}/>
<Drawer.Item
label="I am Driver"
onPress={
() => {}
}
style={styles.drawerItem}
/>
<View style={{ height:1, backgroundColor:'#a8a8a8', marginLeft: 15, marginRight: 15 }}/>
<Drawer.Item
label="Settings"
style={styles.drawerItem}
/>
<View style={{ height:1, backgroundColor:'#a8a8a8', marginLeft: 15, marginRight: 15 }}/>
<Drawer.Item
label="Log Out"
style={styles.drawerItem}
onPress={
() => {}
}
/>
<View style={{ height:1, backgroundColor:'#a8a8a8', marginLeft: 15, marginRight: 15 }}/>
</SafeAreaView>
</ScrollView>
)
}
);
const AppNav = createAppContainer(Menu);
export default class Dashboard extends React.Component {
constructor(props) {
super(props)
}
componentWillReceiveProps(props) {
console.log("Dashboard");
}
render() {
return(
<AppNav />
)
}
}
Hitcher
export default class Hitcher extends React.Component {
state = {
index: 0,
routes: [
{ key: 'first', title: 'My Trips' },
{ key: 'second', title: 'Chats' },
],
};
async _storeItem(key, token) {
try {
var token = await AsyncStorage.setItem(key, token);
return token;
} catch (error) {
console.log(error.message);
}
}
render() {
return (
<View style={styles.container}>
<Appbar.Header
style={{ backgroundColor: '#4ca858' }}>
<Appbar.Action
icon="menu"
color="white"
onPress={() =>
this.props.navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
<Appbar.Action icon={require('../assets/logo_inverted.png')} style={{flex:1, alignSelf:'center'}} size={65} color="white"/>
<Appbar.Action icon="bell" color="white"/>
</Appbar.Header>
<View style={styles.container}>
<TabView
style={{ marginTop: 10 }}
navigationState={this.state}
renderScene={SceneMap({
first: HitcherTrip,
second: HitcherChat,
})}
renderTabBar={props =>
<TabBar
{...props}
labelStyle={styles.label}
indicatorStyle={styles.indicator}
style={styles.tabbar}
getLabelText={({ route }) => route.title}
/>
}
onIndexChange={index => this.setState({ index })} />
</View>
</View>
);
}
}
HitcherTrip
export default class HitcherTrip extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isFetching: false,
spinner: false,
itemId: 0
};
}
componentDidMount() {
this.getTrips();
}
getTrips = () => {
// codes
};
componentWillReceiveProps(props) {
console.log("HitcherTrip");
}
onRefresh() {
this.setState({isFetching: true,},() => {this.getTrips();});
}
createTrip = () => {
Actions.goToOtherLayout();
};
render() {
return(
<View style={styles.scene} >
<FlatList
showsVerticalScrollIndicator={false}
data={this.state.data}
renderItem={({item}) => {
var date = Moment(item.created_at).format('DD MMM');
var now = Moment();
var expired = Moment(item.expired_at);
var status = item.status_name;
if (now > expired && item.status == 0)
status = "Expired";
return (
<TouchableOpacity onPress={
() => {
}
}>
<Spinner
visible={this.state.spinner}
textContent={'Loading...'}
textStyle={styles.spinnerTextStyle}
/>
<View style={styles.container}>
{item.status == 0 ?
<View style={styles.header}>
<Text style={styles.headerLeftActive}>{status}</Text>
<Text style={styles.headerRightActive}>{item.request_no}</Text>
</View> :
<View style={styles.headerInActive}>
<Text style={styles.headerLeftInactive}>{status}</Text>
<Text style={styles.headerRightInactive}>{date}</Text>
</View>
}
<View style={styles.content}>
<Image source={require('../assets/fromto.png')} style={styles.image} />
<View style={styles.textContent}>
<Text style={styles.address}>{item.pickup_location}</Text>
<View style={{flex: 1}} />
<Text style={styles.address}>{item.dropoff_location}</Text>
</View>
</View>
</View>
</TouchableOpacity>
)}
}
keyExtractor={item => item.request_no}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
/>
<TouchableOpacity
style={{
alignItems:'center',
justifyContent:'center',
width:70,
position: 'absolute',
bottom: 10,
right: 10,
height:70,
backgroundColor:'#4ca858',
borderRadius:100,
elevation: 6,
}} onPress={this.createTrip}>
<Text style={{color:'#fff', fontSize: 32}}>+</Text>
</TouchableOpacity>
</View>
)
}
}
On other layout, i have set
Actions.pop(); setTimeout(()=> Actions.refresh(), 500);
to trigger componentWillReceiveProps() when press back button. But it only triggers on Dashboard screen.
How to trigger componentWillReceiveProps() on HitcherTrip? Or maybe trigger HitcherTrip function from Dashboard screen?

Hoisting react-navigation static navigationOptions

I have few class components, that uses react-navigation, when I'm wrapping class component to use HOC, the header dissappears, after doing some research, it seems I need to hoist the static navigationOptions = {}
My themeProvider
export const ThemeContextProvider = ({ children }) => {
const [themeID, setThemeID] = useState();
useEffect(() => {
(async () => {
const storedThemeID = await AsyncStorage.getItem(STORAGE_KEY);
if (storedThemeID) setThemeID(storedThemeID);
else setThemeID(THEMES[1].key);
})();
}, []);
return (
<ThemeContext.Provider value={{ themeID, setThemeID }}>
{!!themeID ? children : null}
</ThemeContext.Provider>
);
};
export function withTheme(Component) {
return props => {
const { themeID, setThemeID } = useContext(ThemeContext);
const getTheme = themeID => THEMES.find(theme => theme.key === themeID);
const setTheme = themeID => {
AsyncStorage.setItem(STORAGE_KEY, themeID);
setThemeID(themeID);
};
return (
<Component
{...props}
themes={THEMES}
theme={getTheme(themeID)}
setTheme={setTheme}
/>
);
};
hoistNonReactStatics(withTheme, HomeScreen); //I've tried this, but header still does not show up.
}
The component in question
export class HomeScreen extends Component {
static navigationOptions = ({ navigation }) => ({
title: 'Dashboard',
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'red',
borderBottomWidth: 0,
},
headerLeft: (
<TouchableOpacity
style={{ paddingLeft: 15 }}
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
>
<Feather name="arrow-left" size={24} color="#ffffff" />
</TouchableOpacity>
),
headerRight: (
<View style={{ flexDirection: 'row' }}>
</View>
),
});
componentDidMount() {
...
}
render() {
const { theme } = this.props;
console.log(theme);
return this.state.loading ? (
<ActivityIndicator
color="red"
size="large"
style={{ alignSelf: 'center', flex: 1 }}
/>
) : (
<View style={[styles.container, { backgroundColor: theme.backgroundColor }]}>
<View style={styles.container2}>
<TouchableOpacity>
<Feather
style={{ top: '60%', left: '28%' }}
name="plus"
size={32}
color="#ffffff"
onPress={this._openNewTaskModal}
/>
</TouchableOpacity>
<TouchableOpacity>
</TouchableOpacity>
</View>
<Feather
style={{ bottom: '5%', left: '85%' }}
name="calendar"
size={22}
color="#ffffff"
/>
<Feather
style={{ bottom: '9%', left: '8%' }}
name="home"
size={22}
color="#ffffff"
/>
</View>
);
}
}
export default withTheme(HomeScreen);
});
I also tried to export it as hoistNonReactStatics in the HomeScreen but no luck, what am I missing?
The solution was to use
export default hoistNonReactStatics(withTheme(HomeScreen), HomeScreen);

React native Drawer Navigator in dynamic image and name

I am new in react native and I want to show data from server I used with below code and don't know how to use here fetch method for call api.
This is drawer navigator:
const AppDrawerNavigator = DrawerNavigator({
Logout: {
screen: Login,
navigationOptions: {
drawerLabel: 'Logout',
drawerIcon: () => (
<Icon name="sign-out" size={18} color="#fff" />
)
},
}
// Test: Test,
},
{
drawerBackgroundColor: "black",
contentComponent: CustomDrawerContentComponent,
contentOptions: {
activeTintColor: '#fff',
inactiveTintColor: '#fff',
activeBackgroundColor: '#f673d7',
itemStyle: {
fontSize: 18,
},
},
});
I want to use dynamic image and name in below component:
const CustomDrawerContentComponent = (props) => (
<View>
<ScrollView>
<View style={styles.profileBg}>
<ImageBackground style={{width: Platform.OS === 'ios' ? 190 : width/1.5, height: 210}} source = {require('../images/banner-2.jpg')}>
<View style={styles.profileHeader}>
<TouchableHighlight>
<View style={styles.profilepicWrap}>
<Image style={styles.profilePic}
source={require('../images/Female-Avatar.png')}
/>
</View>
</TouchableHighlight>
<Text style={styles.name}>Rahul Mishra</Text>
<Text style={styles.changePassword}><Icon name="map-marker" size={16} color="#fff" style={{paddingRight:5}} /> Miamibeach, FL</Text>
</View>
</ImageBackground>
</View>
<DrawerItems
{...props}
getLabel = {(scene) => (
<View style={{borderBottomWidth:1,borderBottomColor: "#fff",width:width/1.9}}>
<Text style={{color:'#fff',fontSize:18,paddingBottom:10,paddingTop:10}}>{props.getLabel(scene)}</Text>
</View>
)}
/>
</ScrollView>
</View>
);
In above code I used const AppDrawerNavigator for calling DrawerNavigator and for contentComponent I used CustomDrawerContentComponent so I am very confusing here how to use API method here.
You can create a component and call this in content component like below:
DrawerUserDetail is a separate component and you can code anything there as normally we are doing...That works for me.
contentComponent: (props) => (
<View>
<ScrollView>
<DrawerUserDetail navigation={props.navigation} />
<DrawerItems
{...props}
getLabel = {(scene) => (
<View style={{borderBottomWidth:0.5,borderBottomColor: "grey",width:width/1.9}}>
<Text style={{color:'#333',fontSize:18,paddingBottom:14,paddingTop:14}}>{props.getLabel(scene)}</Text>
</View>
)}
/>
<DrawerCustom navigation={props.navigation} />
</ScrollView>
</View>
)

In React Native, I want to Add Dynamic Drawer Navigation Item which data come from api(fetch)

Here is my Static code:
class App extends Component {
render() {
return (
<MyApp />
)
}
}
const CustomDrawerContentComponent = (props) => (
<View style={{position:'relative', height:'100%'}}>
<View style={styles.drawerHeader}>
<ImageBackground style={styles.back} source={require('./src/Header/banner.jpg')}>
<View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
<Image
style={styles.drawerImage}
source={require('./src/shirsho.png')} />
</View>
</ImageBackground>
</View>
<View>
{/* <DrawerItems {...props} /> */}
<DrawerItems {...props}
activeTintColor='#000'
activeBackgroundColor='#e3e3e3'
inactiveTintColor='rgba(0, 0, 0, .87)'
inactiveBackgroundColor='transparent'
itemsContainerStyle= {{ marginTop: 0,}}
itemStyle={{ borderBottomWidth: 2, borderBottomColor: '#eee',}}
labelStyle={{fontSize: 16,color: '#000'}}/>
</View>
<View style={{width:100,height:50, position:'absolute', bottom:0,right:30}}>
<Image
style={{width:100, marginLeft: 10,}}
source={require('./src/bdtask.png')} />
</View>
</View>
);
const MyApp = DrawerNavigator({
'হোম' : {
screen : Homepage,
},
'জাতীয়' :{
screen : NationalTab,
},
'খেলা' :{
screen : PlayTab,
},
'প্রশাসন' :{
screen : AdminTab,
},
'অর্থনীতি' :{
screen : EconomicsTab,
},
'বিনোদন' :{
screen : EntertainmentTab,
},
'শিক্ষা' :{
screen : EducationTab,
}
},{
initialRouteName: 'হোম',
drawerPosition: 'left',
contentComponent: CustomDrawerContentComponent,
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
drawerToggleRoute: 'DrawerToggle'
})
export default App
Also, I want to pass value as props with this drawer item.