Implemeting drawer in React native application - menu

I just created my first interface in my React native app. I created a navbar in which there is a menu button to click, so the drawer opens and i can navigate from one screen to another. I intend to use this https://github.com/root-two/react-native-drawer.
I know i need to call open drawer in the menu button when click and here is the code i used, that displays an alert for now
openDrawer(){
this.drawer.open()
}
render() {
return (
<Container>
<Navbar
bgColor={'#C0C0C0'}
title={"Det globale flyktningbildet"}
titleColor="white"
left={{
icon: "ios-menu",
iconColor: "#FFFFFF",
// onPress: () => {alert('Toggle menu ')}
onPress: () => {this.props.openDrawer}
}}
/>
<Drawer
type="static"
// content={<ControlPanel />}
openDrawerOffset={100}
styles={{main: {shadowColor: "#000000", shadowOpacity: 0.4, shadowRadius: 3}}}
tweenHandler={Drawer.tweenPresets.parallax}>
</Drawer>
<View>
<Image
source = { require('./../images/image1_2.png')}
style={[styles.image1, {resizeMode: 'contain'}]}
/>
</View>
</Container>
);
}
So can you please help me implemet the drawer and navigate between different screens

Go through example code in github you will get the idea or you can refer https://stackoverflow.com/a/42748086/6423570
EDIT
You should wrap root container of the screen with Drawer component. The <ControlPanel /> component is the content that should be displayed in the drawer. You could use Touchable Components in the <ControlPanel /> and navigator to navigate between screens. And the openDrawer function is not a prop, call it as this.openDrawer
render() {
return (
<Drawer
type="static"
// content={<ControlPanel />}
openDrawerOffset={100}
styles={{
main: {
shadowColor: "#000000",
shadowOpacity: 0.4,
shadowRadius: 3
}
}}
tweenHandler={Drawer.tweenPresets.parallax}
>
<Container>
<Navbar
bgColor={'#C0C0C0'}
title={"Det globale flyktningbildet"}
titleColor="white"
left={{
icon: "ios-menu",
iconColor: "#FFFFFF",
// onPress: () => {alert('Toggle menu ')}
onPress: () => {this.openDrawer}
}}
/>
<View>
<Image
source = { require('./../images/image1_2.png')}
style={[styles.image1, {resizeMode: 'contain'}]}
/>
</View>
</Container>
</Drawer>
);
}

Related

How to change the text and path of a navigation button?

I have a navbar component, which has a button that transforming me to path (React-Router) "/NEXUM", But, When I'm transformed to NEXUM, i want to change the text of the navbar and the navigation path, so when I click it, it will bring me to a different path, called "/".
const NavBar = () => {
const navigate = useNavigate()
const homeToNavigate = () => {
navigate('/')
}
const Navigation = () => {
navigate('/nexum')
}
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar id="bar">
<Toolbar>
<img onClick={homeToNavigate} className="logo" src={logo}></img>
<Button onClick={Navigation} id='nexumNavigation'> להכנסת קובץ אקסל ישיר </Button>
</Toolbar>
</AppBar>
</Box>
)
}
export default NavBar
This is The nav bar component, The "navBar" component is used in both "HomePage" Component that I'm using and "SpagetiComponent", So as I said, I need the purpose of the button to change, I tried doing it with props, but I was unsuccessful, if you have an idea, please let me know.
let location = useLocation();
<Button onClick={location.pathName==="/NEXUM"?homeToNavigate:Navigation} id='nexumNavigation'>{location.pathName==="/NEXUM"?"go home":"go NEXUM"} </Button>

Error: `useTheme` must be used within `NativeBaseConfigProvider`

In my project I experienced the above error
The error explanation :
This error is located at:
in Container
in ProductContainer (created by App)
in RCTView (created by View)
in View (created by App)
in App (created by ExpoRoot)
in ExpoRoot
in RCTView (created by View)
in View (created by AppContainer)
in RCTView (created by View)
in View (created by AppContainer)
in AppContainer
ProductContainer.js:
import React, { useState, useEffect } from 'react'
import { View, StyleSheet, ActivityIndicator, FlatList, Text} from 'react-native'
import { Container, Header, Icon, Item, Input, Text } from 'native-base';
import ProductList from './ProductList';
const data = require('../../assets/data/products.json');
const ProductContainer = () => {
const [products, setProducts ] = useState([]);
useEffect(() => {
setProducts(data);
return () => {
setProducts([])
}
}, [])
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
})
return (
<Container>
<Header searchBar rounded>
</Header>
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.brand}
item={item}/>}
keyExtractor={item => item.brand}
/>
</View>
</View>
</Container>
)
}
export default ProductContainer;
I managed to solve this error from this github issue: https://github.com/GeekyAnts/NativeBase/issues/4303.
Apparently the problem is that you need to wrap app elements in <NativeBaseProvider>.
In this example you can see how the native base provider wraps all other providers, if the <NativeBaseProvider> is not at the top, it will throw the error: useTheme must be used within `NativeBaseConfigProvider
export default function App() {
return (
<NativeBaseProvider>
<SafeAreaProvider>
<AuthProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar />
</AuthProvider>
</SafeAreaProvider>
</NativeBaseProvider>
);
}
<Container>
<Header searchBar rounded>
</Header>
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.brand}
item={item}/>}
keyExtractor={item => item.brand}
/>
</View>
</View>
</Container>
wrap all these Container tag and its contents inside...
If the issue is happening in Testing you can simply pass initialWindowMetrics to NativeBaseProvider in your tests.
const inset = {
frame: { x: 0, y: 0, width: 0, height: 0 },
insets: { top: 0, left: 0, right: 0, bottom: 0 },
};
<NativeBaseProvider initialWindowMetrics={inset}>
{children}
</NativeBaseProvider>;

Adding checkbox in between text description in react native

I have a view where I display a Heading and details which I get from server as below.
Now, in the question description there is a tag __CB__ which I need to replace with the checkbox, so, instead of that tag there will be a checkbox and rest of the text will continue as usual. I have separated the text based on tag and placed a checkbox in between but I haven't been able to align the view, either it gets arranged columnwise or if I try to arrange in row the text doesn't continue. Here is what I've tried.
Try 1:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={styles.checkBoxTextContainer}>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</View>
</ScrollView>
Styles
checkBoxTextContainer: {
flex: 1,
flexDirection: "row"
},
checkBoxStyle: {
width: 20,
height: 20
}
Result:
Try 2:
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<Text style={styles.questionText}>{questionText1}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
// leftText={questionText1}
// rightText={questionText2}
/>
<Text style={styles.questionText}>{questionText2}</Text>
</ScrollView>
Result:
I need the checkbox to continue in between text like the tag in my original image. Any help is appreciated.
Below is sample working code for your scenario.
import React, { Component } from 'react'
import { View, Text, StyleSheet } from 'react-native'
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap'
},
cb: {
width: 10,
height: 10,
borderWidth: 2,
borderRadius: 2,
borderColor: 'red',
marginTop: 4,
marginHorizontal: 3,
}
})
const sampleData = [ 'Lorem', 'ipsum', 'dolor', 'sit', 'amet',
'CB',
'consectetur', 'adipiscing', 'elit.', 'Curabitur',
'CB',
' nunc', 'vel', 'scelerisque', 'tempus.', 'CB', 'Morbi', 'luc', 'abcd', 'xyzw'
]
const CheckBox = () => (
<View style={styles.cb} />
)
export default class CheckText extends Component {
renderData = (data) => {
const views = data.map((item) => {
if (item === 'CB') { return <CheckBox />}
return (<Text>{item}</Text>)
})
return views
}
render() {
return (
<View style={styles.container}>
{this.renderData(sampleData)}
</View>
)
}
}
And this is snapshot of output
Note:
I have parsed the text into array of strings. This is the key logic here. The way you decide to tokenize your input text will affect the rendering of your component. When I tried long strings as token, flexWrap: 'wrap' didn't work properly. See this issue for more details. Tokenizing into single words may do the job.
try to wrap the Text and Checkbox into <Text> tag.
Please try below solution. It may help you.
<ScrollView
style={styles.scrollStyle}
scrollEnabled={scrollEnabled}
onContentSizeChange={this.onContentSizeChange}
>
<View style={{
width:'100%',
flexDirection: "row"
}}>
// wrap into text tag
<Text>
// add space after first text
<Text style={styles.questionText}>{questionText1+" "}</Text>
<CheckBox
style={styles.checkboxStyle}
onClick={this.checkboxClick}
isChecked={this.state.isChecked}
checkedImage={<Image source={Images.checkBoxTick} />}
unCheckedImage={<Image source={Images.checkBoxEmpty} />}
/>
// add space before second text
<Text style={styles.questionText}>{" "+questionText2}</Text>
</Text>
</View>
</ScrollView>

Retrieving Geolocation of user without index.html

Hey I'm making a web application that has to track a user location after button is clicked.
I have been using the M.E.R.N stack for this and so far with the tutorials I watched they haven't needed any index.html file just pure JavaScript.
I have implement Google maps on my site without using any HTML files.
This is the code I want to implement
But without having to create a index.html.
How can I add this code to my main.js file without the HTML file?
THIS IS HOW I HAVE GOOGLE MAPS SETUP IN MY LANDING PAGE
import React, { Component } from 'react';
import { Grid, Cell } from 'react-mdl';
import Paper from '#material-ui/core/Paper';
import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';
//THIS IS THE LANDING PAGE.
const mapStyles = {
width: '100%',
height: '100%'
};
export class LandingPage extends Component {
render() {
return (
<Map
google={this.props.google}
zoom={3}
style={mapStyles}
initialCenter={{
lat: 28.871812,
lng: -34.814106
}}
>
</Map>
);
}
}
export default GoogleApiWrapper({
apiKey: 'API-KEY'
})(LandingPage);
THIS IS NAVBAR WITH THE ENTER CODE BUTTON THAT SHOULD REQUEST GEOLOCATION ON CLICK
importS{}
//THIS IS THE NAVIGATION BAR PAGE.
export default class NavBar extends React.Component {
constructor(props) {
super(props);
this.toggleNavbar = this.toggleNavbar.bind(this);
this.state = {
collapsed: true
};
}
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
toggleNavbar() {
this.setState({
collapsed: !this.state.collapsed
});
}
render() {
return (
<div>
<Navbar style={{background: '#948E99', flex: 1,
background: '-webkit-linear-gradient(to right, #2E1437, #948E99)',
background: 'linear-gradient(to right, #2E1437, #948E99)'}} dark>
<NavbarToggler color="white" onClick={this.toggleNavbar} className="mr-2" />
<Button style={{color: 'white'}} href="/" className="mrauto">DigitalDollar</Button>
<Button style={{color: 'white'}} onClick={this.handleClickOpen} className="mr-auto">Enter Code</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Enter Code</DialogTitle>
<DialogContent>
<DialogContentText>
Thank you for participating in the DigitalDollar global run! By entering this code we will
add your location to our map, please enter your magnificint code here. Thank you for your
participation.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="Code"
label="Enter Code"
type="Code"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary">
Subscribe
</Button>
</DialogActions>
</Dialog>
<Collapse isOpen={!this.state.collapsed} navbar>
<Nav navbar>
<NavItem>
<NavLink href="/">Home</NavLink>
</NavItem>
<NavItem>
<NavLink href="/about">About</NavLink>
</NavItem>
<NavItem>
<NavLink href="https://github.com/CH-SYR3" rel="noopener noreferrer" target="_blank">GitHub</NavLink>
</NavItem>
<NavItem>
<NavLink href="https://www.paypal.com/us/home" rel="noopener noreferrer" target="_blank">Buy Me A Coffee?</NavLink>
</NavItem>
</Nav>
</Collapse>
</Navbar>
<div>
<Navbar color="light" light expand="md">
<Nav className="NavTabs" navbar>
<NavItem>
<NavLink href="/">Map</NavLink>
</NavItem>
<NavItem>
<NavLink href="/time">Time</NavLink>
</NavItem>
<NavItem>
<NavLink href="/hello">Hello</NavLink>
</NavItem>
</Nav>
</Navbar>
</div>
</div>
);
}
It's not a file, just an html5 standard that works in browsers. In the link you provide, the navigation language is in the script tag. If you wrap the navigator.geolocation method in a function getUserLoc() that does little more than setState with the coordinates on click, you will be able to update the map's position by setting state. You'd set the initial state in LandingPage's constructor, then pass `getUserLoc() function to your NavBar component where it can be run with this.props.getUserLoc().
const mapStyles = {
width: '100%',
height: '100%'
};
export class LandingPage extends Component {
constructor(props) {
super(props)
this.state={
lat: 28.871812,
lng: -34.814106
}
this.getUserLoc = this.getUserLoc.bind(this)
}
getUserLoc() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
this.setState({
userLat: pos.lat,
userLng: pos.lng
})
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}
render() {
return(
<div>
<Map
google={this.props.google}
zoom={3}
style={mapStyles}
initialCenter={{
lat: this.state.userLat,
lng: this.state.userLng
}}
>
</Map>
<NavBar getUserLoc={this.getUserLoc}/>
</div>
)
}
}

Tabs in react not displaying appropriate content

I am using the Tab from semantic-ui-react. I need to display a list of days and their corresponding events for that day. However, an event created in one day shows up in the other day too.
As seen, I created an event in day 1, but it shows up in day 2, which is incorrect. Here's how I generate the tab data:
const panes = selectedDays.map((day, index) => {
const count = index + 1;
return {
menuItem: `Day ${count}`,
render: () => <Tab.Pane><Agenda day={day} index={count} /></Tab.Pane>
};
});
this.setState({ panes });
Component Code
{
currentIndex === 3 &&
<Fragment>
<Tab
menu={{ pointing: true }}
panes={this.state.panes}
/>
<Button className='formnext' onClick={this.handlePrevious}>
<FontAwesome name='angle-left' style={{ color: 'white', fontSize: '2.2rem' }} className='logout' />
</Button>
<Button className='formnext' onClick={this.handleNext}>
<FontAwesome name='angle-right' style={{ color: 'white', fontSize: '2.2rem' }} className='logout' />
</Button>
</Fragment>
}
If I add a key attribute to the Tab.Pane or Agenda component, clicking on a tab header, just clears my state and I am left with no data. Any idea how to solve this one?

Resources