I created a drawer (react-navigation) in Routes.js and I have a Button in HamburgerBtn.js. I wish to invoke the call on the button to open the drawer with my button. I do not understand how to get this even from outside of routes into the button.
#HamburgerBtn.js;import Hamburger from 'react-native-hamburger';
import React, {Component} from 'react';
import styles from './Component.style';
import {
Text,
View
} from 'react-native';
import {DrawerNavigator} from 'react-navigation';
import {NavigationActions} from 'react-navigation';
class HamburgerBtn extends Component {
constructor(props){
super(props);
this.state = {
active: false,
}
}
openControlPanel = () => {
this.props.navigation.navigate('DrawerOpen'); // open drawer
};
render () {
//onPress={()=> {this.setState({active: !this.state.active});this.props.navigation.navigate('DrawerOpen');}}/>
return (
<View style={styles.hamburgerBtnHome}>
<Hamburger active={this.state.active}
type = "arrow"
color = "black"
onPress={()=> {this.props.openControlPanel()}}
/>
</View>
);
}
}
export default HamburgerBtn;
--routes.js--
import Connect from './Connect/Connect';
import Setup from './Setup/Setup';
import Update from './Update/Update';
import homePage from './homePage'
import SideMenu from './SideMenu/SideMenu';
import {DrawerNavigator} from 'react-navigation';
openControlPanel = () => {
this.props.navigation.navigate('DrawerOpen'); // open drawer
};
export default DrawerNavigator({
homePage: {
screen: homePage
},
Connect: {
screen: Connect
},
Setup: {
screen: Setup
},
Update: {
screen: Update
}
}, {
contentComponent: SideMenu,
drawerWidth: 300
});
--homepage.js--
import React, {Component} from 'react';
import {
Text,
View
} from 'react-native';
import Hamburger from './Components/HamburgerBtn';
class homePage extends Component {
render () {
return (
<View style={{padding: 50}}>
<Hamburger/>
<Text>
HomePage
</Text>
</View>
);
}
}
export default homePage;
--hamburger--
import Hamburger from 'react-native-hamburger';
import React, {Component} from 'react';
import styles from './Component.style';
import {
Text,
View
} from 'react-native';
import PropTypes from 'prop-types';
import {NavigationActions} from 'react-navigation';
class HamburgerBtn extends Component {
constructor(props){
super(props);
this.state = {
active: false,
}
}
onPress = () => {
this.setState({active: !this.state.active});
this.props.onPress();
};
render () {
//onPress={()=> {this.setState({active: !this.state.active});this.props.navigation.navigate('DrawerOpen');}}/>
return (
<View style={styles.hamburgerBtnHome}>
<Hamburger active={this.state.active}
type = "arrow"
color = "black"
onPress={() => this.onPress()}
/>
</View>
);
}
}
export default HamburgerBtn;
--homepage--
import React, {Component} from 'react';
import {
Text,
View
} from 'react-native';
import Hamburger from './Components/HamburgerBtn';
class homePage extends Component {
openControlPanel = () => {
this.props.navigation.navigate('DrawerOpen'); // open drawer
};
render () {
return (
<View style={{padding: 50}}>
<Hamburger onPress={() => this.openControlPanel()} />
<Text>
HomePage
</Text>
</View>
);
}
}
export default homePage;
Related
Good evening everyone,
I created two screens and I would like to pass the context to one of this screen but it doesn't work.
Here what I have so far :
App :
import React from 'react';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import HomeScreen from "./src/screens/HomeScreen";
import ExpenseScreen from "./src/screens/ExpenseScreen";
import BalanceScreen from "./src/screens/BalanceScreen";
import {ExpenseProvider} from "./src/context/ExpenseContext";
const navigator = createStackNavigator(
{
Home:HomeScreen,
Expense:ExpenseScreen,
Balance: BalanceScreen
},
{
initialRouteName:"Home",
defaultNavigationOptions:{
title:"App",
}
}
)
const App = createAppContainer(navigator);
export default () => {
return <ExpenseProvider>
<App/>
</ExpenseProvider>
};
HomeScreen:
import React from "react";
import { Text, StyleSheet, View, Button} from "react-native";
const HomeScreen = ({navigation}) => {
return(
<View>
<Text style={styles.text}>HomeScreen</Text>
{/*Shows default display*/}
<Button
onPress={()=> navigation.navigate('Expense')}
title="Expense Tracker"
/>
<Button
onPress={()=> navigation.navigate('Balance')}
title="Balance"
/>
</View>
)
};
const styles = StyleSheet.create({
text: {
fontSize: 30
}
});
export default HomeScreen;
Provider :
import React from 'react';
const ExpenseContext = React.createContext();
export const ExpenseProvider = ({children}) => {
const expensePosts = [
{title: 'Expense Post #1'},
{title: 'Expense Post #2'},
{title: 'Expense Post #3'}
]
return <ExpenseContext.Provider value={expensePosts}>{children}</ExpenseContext.Provider>
};
export default ExpenseContext;
Screen :
import React, {useContext} from "react";
import { Text, StyleSheet, View, Button, Flatlist } from "react-native";
import ExpenseContext from '../context/ExpenseContext';
const ExpenseScreen = () => {
const expensePosts = useContext(ExpenseContext)
return(
<View>
<Text style={styles.text}>Expense Tracker</Text>
<Flatlist
data={expensePosts}
keyExtractor={(expensePost) => expensePost.title}
renderItem={({item}) => {
return <Text>{item.title}</Text>
}}
/>
</View>
)
};
const styles = StyleSheet.create({
text: {
fontSize: 30
}
});
export default ExpenseScreen;
I am trying to import the context into the "expenseScreen" but it doesn't work.
The error message I have is " element type is invalid: expected a string or a class but got undefined. You likely forgot to export your component from the file it's defined in or you might have mixed up default and name imports. Check the render method of 'ExpenseScreen'".
What am I missing ?
Does the Expenseprovider exported in the App only applies for the 'homeScreen' ?
Thank you very much in advance and hope this is clear enough.
I am coding an application that will have more than one page. I use '#react-navigation/native' and '#react-navigation/stack' to navigate between these pages. It works correctly when I write a function name in Stack.Screen's component. But I did not understand how the class call was made.
Api.js
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
const Stack = createStackNavigator();
export default function App(props) {
// Load any resources or data that we need prior to rendering the app
return (
<View style={styles.container}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Homa Page" component={HomeScreen}/>
</Stack.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
screens/HomeScreen.js
import * as React from 'react';
import { Text, View } from 'react-native';
import { getSummary } from '../data/getSummary.js';
export class HomeScreen extends Component {
constructor(props){
super(props);
this.state ={
isLoading: true,
}
this.getSummary = getSummary.bind(this)
}
componentDidMount(){
this.getSummary;
}
render(){
return (
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={ this.state.data}
keyExtractor={(item) => item.CountryCode}
renderItem={({ item }) => (
<View>
<Text>Country:{item.CountryCode}</Text>>
</View>
)}
/>
</View>
);
}
}
How I can re-render a web-view running inside a app built with react native. For exemple: The cart tab need to load the same url every time I click on it.
This is the cart class:
import React, { useState } from 'react';
import { ActivityIndicator, WebView, View, Button, ScrollView,
RefreshControl,
Text, } from 'react-native';
import Config from '../config';
export default class CarrinhoScreen extends React.Component {
reload() {
this.myWebView.reload()
}
render() {
return (
<>
<View style={{ flex: 1 }}>
<WebView
source={{ uri: 'https://www.genieshopp.com/checkout/cart/' }}
userAgent='bring-app'
startInLoadingState={true}
ref={(ref) => this.myWebView = ref}
/>
</View>
</>
)
}
};
Here is where the tabNavigator is created:
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import CarrinhoScreen from '../screens/CarrinhoScreen';
const config = Platform.select({
web: { headerMode: 'screen' },
default: {},
});
const CarrinhoStack = createStackNavigator(
{
Carrinho: CarrinhoScreen
},
config
);
CarrinhoStack.navigationOptions = {
tabBarLabel: 'Carrinho',
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} name={Platform.OS === 'ios' ? 'ios-cart' : 'md-cart'}/>
),
};
CarrinhoStack.path = '';
const tabNavigator = createBottomTabNavigator(
{
CarrinhoStack,
},
{
backBehavior: 'history'
}
);
tabNavigator.path = '';
export default tabNavigator;
I know there is the myWebView.reload(), but I want to know how I reload it when the bottom tab is switched or when I click on the same icon.
Solved by putting resetOnBlur: CarrinhoScreen after backBehavior: history
You can put any other screen you want to reset on there.
I get this error that getInputData is undefined, please what am I doing wrong?
getInputData simply gets the users inputs....I'm using redux. I defined getInputData in my function called handleInput or is it not well defined......
import React from "react";
import styles from "./style";
import { Text } from "react-native";
import { View, Input, InputGroup } from "native-base";
import Icon from "react-native-vector-icons/FontAwesome";
import { SearchBar } from "react-native-elements";
export const SearchBox = ({ getInputData }) => {
const handleInput = (key, val) => {
getInputData({
key,
value: val
});
};
return (
<View style={styles.searchBox}>
<View style={styles.inputWrapper}>
<Text style={styles.label}>PICK UP</Text>
<InputGroup>
<Icon name="search" size={15} color="#FF5E3A" />
<Input
style={styles.inputSearch}
placeholder="Enter Pickup Location"
onChangeText={handleInput.bind(this, "pickUp")}
/>
</InputGroup>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.label}>DROP OFF</Text>
<InputGroup>
<Icon name="search" size={15} color="#FF5E3A" />
<Input
style={styles.inputSearch}
placeholder="Enter Drop Off Location"
onChangeText={handleInput.bind(this, "dropOff")}
/>
</InputGroup>
</View>
</View>
);
};
export default SearchBox;
this is my mapContainer.js where inputData is passed down as a prop to SearchBox.
import React from 'react';
import styles from './style';
import {View} from 'native-base';
import MapView from 'react-native-maps';
import SearchBox from '../SearchBox';
import SearchResults from '../SearchResults';
export const MapContainer= ({region, getInputData}) => {
return(
<View style={styles.container}>
<MapView
provider={MapView.PROVIDER_GOOGLE}
style={styles.map}
region={region}
>
<MapView.Marker
coordinate={region}
pinColor="green"/>
</MapView>
<SearchBox getInputData={getInputData}/>
<SearchResults/>
</View>
)
}
export default MapContainer
This is where I connect mapStateToProps to my mapActionCreators
import {connect} from "react-redux";
import {
getCurrentLocation,
getInputData,
} from '../../actions/currentLocation';
import { MapContainer } from '../MapContainer';
import Home from "../../screens/Home";
const mapStateToProps=(state)=>({
region:state.region,
inputData:state.inputData || {}
});
const mapActionCreators = {
getCurrentLocation,
getInputData,
};
export default connect(mapStateToProps,mapActionCreators)(Home);
this is my Home code.
import React from 'react';
import { View, Text } from 'react-native';
import styles from './styles';
import { Container} from 'native-base';
import { MapContainer} from '../../components/MapContainer';
import GetLocation from 'react-native-get-location'
import {Dimensions} from "react-native";
const {width,height}=Dimensions.get("window");
const ASPECT_RATIO=width/height;
const LATITUDE_DELTA=0.922;
const LONGITUDE_DELTA=ASPECT_RATIO*LATITUDE_DELTA
class Home extends React.Component{
constructor(props){
super(props);
this.state={
latitude:3.14662,
longitude:101.6984,
latitudeDelta:LATITUDE_DELTA,
longitudeDelta:LONGITUDE_DELTA
}
}
componentDidMount(){
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then(location => {
this.setState({
latitude:location.latitude,
longitude:location.longitude
})
console.log(location)
console.log(this.state.longitude);
})
.catch(error => {
const { code, message } = error;
console.warn(code, message);
}) }
render(){
const region={
latitude:this.state.latitude,
longitude:this.state.longitude,
latitudeDelta:this.state.latitudeDelta,
longitudeDelta:this.state.longitudeDelta
}
return(
<Container>
<MapContainer region={region} getInputData={this.props.getInputData} />
</Container>
);
}
}
export default Home;
You should use connect on the Home page like
import React from 'react';
import {connect} from "react-redux";
import { View, Text } from 'react-native';
import styles from './styles';
import { Container} from 'native-base';
import { MapContainer} from '../../components/MapContainer';
import GetLocation from 'react-native-get-location'
import {Dimensions} from "react-native";
import {
getCurrentLocation,
getInputData,
} from '../../actions/currentLocation';
const {width,height}=Dimensions.get("window");
const ASPECT_RATIO=width/height;
const LATITUDE_DELTA=0.922;
const LONGITUDE_DELTA=ASPECT_RATIO*LATITUDE_DELTA
class Home extends React.Component{
constructor(props){
super(props);
this.state={
latitude:3.14662,
longitude:101.6984,
latitudeDelta:LATITUDE_DELTA,
longitudeDelta:LONGITUDE_DELTA
}
}
componentDidMount(){
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then(location => {
this.setState({
latitude:location.latitude,
longitude:location.longitude
})
console.log(location)
console.log(this.state.longitude);
})
.catch(error => {
const { code, message } = error;
console.warn(code, message);
}) }
render(){
const region={
latitude:this.state.latitude,
longitude:this.state.longitude,
latitudeDelta:this.state.latitudeDelta,
longitudeDelta:this.state.longitudeDelta
}
return(
<Container>
<MapContainer region={region} getInputData={this.props.getInputData} />
</Container>
);
}
}
const mapStateToProps=(state)=>({
region:state.region,
inputData:state.inputData || {}
});
const mapActionCreators = {
getCurrentLocation,
getInputData,
};
export default connect(mapStateToProps,mapActionCreators)(Home);
In my app, I have Login Screen, ForgotPassword Screen and SignUp Screen. In SignUp Screen I have used react-native-swiper to displays three step's slides of signup process. And I have wrap-up these screens in StackNavigator and render this StackNavigator as a root component in my App.js.
Here is my StackNavigator :
Router.js
import { createDrawerNavigator, createAppContainer, createStackNavigator } from 'react-navigation';
import Login from './src/containers/Login';
import SignUp from './src/containers/SignUp';
import ForgotPassword from './src/containers/ForgotPassword';
const AuthStackNavigator = createStackNavigator({
Login: {
screen: Login
},
ForgotPassword: {
screen: ForgotPassword
},
SignUp: {
screen: SignUp
},
});
const Router = createAppContainer(AuthStackNavigator)
export default Router
App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import configureStore from './src/store/configureStore';
import Router from './Router';
const store = configureStore()
class App extends Component {
render() {
return (
<Provider store={store}>
<Router />
</Provider>
);
}
}
export default App
SignUp.js
import React, { Component } from 'react';
import { View, StyleSheet, TouchableOpacity, KeyboardAvoidingView, Platform, Dimensions } from 'react-native';
import Swiper from 'react-native-swiper';
import Colors from '../../config/Colors';
import Logo from '../components/Logo';
import MText from '../components/MText';
import StepButton from '../components/StepButton';
import SignUpStepOne from './SignUpStepOne';
import SignUpStepTwo from './SignUpStepTwo';
import SignUpStepThree from './SignUpStepThree';
class SignUp extends Component {
static navigationOptions = ({navigation}) => ({
header: null
});
constructor(props) {
super(props);
this.state = {
activeStep: 0
};
}
slideToNext = () => {
this.swiper.scrollBy(1, true);
this.setState(prevState => ({
activeStep: prevState.activeStep + 1
}))
}
slideToPrev = () => {
this.setState(prevState => ({
activeStep: prevState.activeStep - 1
}), () => {
this.swiper.scrollBy(-1, true);
})
}
render() {
<KeyboardAvoidingView style={styles.container} behavior="padding">
<View style={{ flex: 1, paddingHorizontal: 10 }}>
<Logo />
<Swiper
style={{
}}
ref={(swiper) => { this.swiper = swiper; }}
containerStyle={{ flex: 1 }}
showsButtons={false}
showsPagination={false}
loop={false}
scrollEnabled={false}
onIndexChanged={(activeStep) => {
this.setState({
activeStep
})
}}
>
<SignUpStepOne onNext={this.slideToNext} />
<SignUpStepTwo onNext={this.slideToNext} onPrev={this.slideToPrev} />
<SignUpStepThree onNext={this.slideToNext} onPrev={this.slideToPrev} />
</Swiper>
</View>
</KeyboardAvoidingView>
}
}
But, the problem is that when I navigate from Login screen to SignUp screen using this.props.navigation.navigate('SignUp'), Swiper componen not displaying anything in SignUp screen. It just blank. For android it working properly, For IOS it is not working.
And another thing to note is that If I just render SignUp screen as a root in App.js then it is working properly.
And also If I set SignUp screen as a initial screen in my StackNavigator then also it's working.
Please anyone help me what's going wrong here ?
I Have found the solution.
Add removeClippedSubviews={false} props to swiper. Then It will work.
If Swiper isn't working use these props
removeClippedSubviews={false}
scrollEnabled={true}