recently started working on an app using https://github.com/start-react/native-starter-kit
Heres my component:
import React, { Component } from "react";
import { TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import BlankPage2 from "../blankPage2";
import DrawBar from "../drawBar";
import TopNav from "../topNav";
import { DrawerNavigator, NavigationActions } from "react-navigation";
import {
Container,
Header,
Title,
Content,
Text,
Button,
Icon,
Left,
Body,
Right,
Image,
} from "native-base";
import { Grid, Row } from "react-native-easy-grid";
import { setIndex } from "../../actions/list";
import { openDrawer } from "../../actions/drawer";
import styles from "./styles";
class News extends Component {
static navigationOptions = {
header: null
};
render() {
return (
<Container style={styles.container}>
<Header>
<Left>
<Button
transparent
onPress={() => DrawerNav.navigate("DrawerOpen")}>
<Icon active name="menu" />
</Button>
</Left>
<Body>
<Title>News</Title>
</Body>
<Right>
</Right>
</Header>
<Content scrollEnabled={false}>
<TopNav navigation={this.props.navigation}></TopNav>
<Grid style={styles.mt}>
{this.props.list.map((item, i) => (
<Row key={i}>
<TouchableOpacity
style={styles.row}
onPress={() =>
this.props.navigation.navigate("BlankPage", {
name: { item }
})}>
<Image source={{uri: 'https://i.vimeocdn.com/portrait/58832_300x300.jpg'}} />
<Text style={styles.text}>{item}</Text>
</TouchableOpacity>
</Row>
))}
</Grid>
</Content>
</Container>
);
}
}
function bindAction(dispatch) {
return {
setIndex: index => dispatch(setIndex(index)),
openDrawer: () => dispatch(openDrawer())
};
}
const mapStateToProps = state => ({
name: state.user.name,
list: state.list.list
});
const NewsSwagger = connect(mapStateToProps, bindAction)(News);
const DrawNav = DrawerNavigator(
{
News: { screen: NewsSwagger },
BlankPage2: { screen: BlankPage2 }
},
{
contentComponent: props => <DrawBar {...props} />
}
);
const DrawerNav = null;
DrawNav.navigationOptions = ({ navigation }) => {
DrawerNav = navigation;
return {
header: null
};
};
export default DrawNav;
And of course, heres my error:
And i have no clue why this is happening. As soon as i remove the Image tag, error goes away. I can't really export the News Component, becouse i am using the Drawer thingy(check starter-kit-demo).
Edit: Error happens on IOS. Iphone 6 emulator.
You are importing Image from native-base when you should be importing it from react-native
import {
Container,
Header,
Title,
Content,
Text,
Button,
Icon,
Left,
Body,
Right,
Image // remove this one
} from "native-base";
And add
import {
TouchableOpacity,
Image
} from "react-native";
Also you'll have to add a height & width for a proper render.
<Image
style={{width: 300, height: 300}}
source={{uri: 'https://i.vimeocdn.com/portrait/58832_300x300.jpg'}}
/>
Related
Assume the fetch returns an object of 150 items, of this 150 items only 20 are rendered as components. I've tried FlatList, LargeList and have watched multiple youtube videos and can't seem to get it to work.
I run this on the Expo Dev app, and when I scroll to the bottom of the list, no more load. Only about 20 cards are rendered.
This is what the end of the screen looks like, I try scroll down more and no more load.
Screen shot when scrolling to the bottom:
Screen shot after scrolling to the bottom:
This is the code for my home screen:
import React, { useEffect, useState } from 'react';
import {StyleSheet, ScrollView, Alert, ActivityIndicator} from 'react-native';
import HeaderTabs from '../components/HeaderTabs';
import Screen from '../components/Screen'
import Categories from '../components/Categories'
import SearchBar from '../components/SearchBar'
import ServiceItem from "../components/ServiceItem";
import tailwind from 'tailwind-react-native-classnames';
import { localServices } from '../data/localServices';
import colors from '../configs/colors'
const YELP_API_KEY = "RF2K7bL57gPbve8oBSiX23GYdCVxIl-KedmS-lyEafEZKNIn6DgsN6j88JvHolhiT4LH-VxT2NvDwgzl9yCTW-5REbbu3Cl5vwqCNUtGhnzzScPinQciOvs6PVBtY3Yx";
const HomeScreen = () => {
const [serviceData, setServiceData] = useState(localServices)
const [city, setCity] = useState("San Francisco")
const [activeTab, setActiveTab] = useState("Delivery");
const [loading, setLoading] = useState(false)
const getServicesFromYelp = () => {
const yelpUrl = `https://api.yelp.com/v3/businesses/search?term=Home+Services&location=${city}`;
const apiOptions = {
headers: {
Authorization: `Bearer ${YELP_API_KEY}`,
},
};
setLoading(true)
return fetch(yelpUrl, apiOptions)
.then((res) => res.json())
.then((json) => {
setLoading(false)
if(json.error) return Alert.alert('Sorry', json.error.description);
setServiceData(
json?.businesses?.filter((business) =>
// business.transactions.includes(activeTab.toLowerCase())
business
// city.includes(business.location.city)
)
)
}
);
};
useEffect(() => {
getServicesFromYelp();
}, [city, activeTab]);
return (
<Screen style={tailwind`bg-white flex-1`}>
<HeaderTabs activeTab={activeTab} setActiveTab={setActiveTab} />
<SearchBar setCity={setCity} city={city} />
<ScrollView style={tailwind`flex-1`} showsVerticalScrollIndicator={false}>
<Categories />
{loading && <ActivityIndicator size="large" color={colors.primary} style={tailwind`mt-2 mb-6`} />}
<ServiceItem serviceData={serviceData} />
</ScrollView>
</Screen>
);
}
const styles = StyleSheet.create({})
export default HomeScreen;
This is the code for the individual components:
ServiceItem.js:
import React from 'react';
import { View } from 'react-native';
import ServiceItemCard from "./ServiceItemCard";
const ServiceItem = ({ serviceData }) => {
return (
<View>
{serviceData?.map((item, index) => (
<ServiceItemCard key={index} item={item} />
))}
</View>
);
}
export default ServiceItem;
ServiceItemCard.js:
import React, { useState } from 'react';
import { Image, Text, TouchableOpacity, View, FlatList } from 'react-native';
import tailwind from 'tailwind-react-native-classnames';
import { Entypo } from '#expo/vector-icons';
import { MaterialCommunityIcons } from '#expo/vector-icons';
const ServiceItemCard = ({ item }) => {
const [loved, setLoved] = useState(false)
return (
<View style={tailwind`mx-4 mb-4`}>
<Image
source={{ uri: item.image_url ? item.image_url : null}}
style={tailwind`w-full h-48 rounded-lg`}
/>
<TouchableOpacity style={tailwind`absolute top-2 right-2`} onPress={() => setLoved(e => !e)}>
<Entypo name={`${loved ? 'heart' : 'heart-outlined'}`} size={28} color="#fff" />
</TouchableOpacity>
<View style={tailwind`flex-row items-center mt-1`}>
<View style={tailwind`flex-grow`}>
<Text style={tailwind`font-bold text-lg`} numberOfLines={1}>{item.name}</Text>
<View style={tailwind`flex-row items-center`}>
<MaterialCommunityIcons name="clock-time-four" size={13} color="#06C167" />
<Text style={tailwind`text-xs text-gray-700`}> 20-30 • min • {item.price}</Text>
</View>
</View>
<View style={tailwind`w-8 h-8 justify-center items-center bg-gray-100 rounded-full`}>
<Text style={tailwind`text-gray-600 text-xs`}>{item.rating}</Text>
</View>
</View>
</View>
)
}
export default ServiceItemCard;
I tried using FlatList, LargeList and messing around with infinite scrolling
The function I am not able to run is the navigation functions in my example it's
this.this.props.navigation.goBack()
My Login File is posted below but the part with the problem is the short snippet
The error I am getting is: TypeError: undefined is not an object (evaluating 'LogIn.props.navigation')
First failed Snippet
static navigationOptions = {
headerLeft: () => (
<Button
onPress={()=>this.props.navigation.goBack()}
title="cancel"
color={colors.black}
/>
),
};
LogIn.js
import React, { Component } from 'react';
import { PropTypes } from 'prop-types';
import Icon from 'react-native-vector-icons/FontAwesome';
import colors from '../styles/colors';
import {
View,
Text,
ScrollView,
StyleSheet,
KeyboardAvoidingView,
Button
} from 'react-native';
import InputField from '../components/form/InputField';
import NexArrowButton from '../components/buttons/NextArrowButton';
import Notification from '../components/Notification';
export default class LogIn extends Component{
constructor(props){
super(props);
this.state ={
formValid:false,
validEmail:false,
emailAddress:'',
validPassword:false,
}
this.handleNextButton = this.handleNextButton.bind(this)
this.handleCloseNotification = this.handleCloseNotification.bind(this)
this.handleEmailChange = this.handleEmailChange.bind(this);
}
static navigationOptions = {
headerLeft: () => (
<Button
onPress={()=>this.props.navigation.goBack()}
title="cancel"
color={colors.black}
/>
),
};
handleNextButton(){
if(this.state.emailAddress === 'admin#mail.com'){
this.setState({formValid:true})
} else{
this.setState({formValid: false});
}
}
handleCloseNotification(){
this.setState({formValid:true });
}
handleEmailChange(email){
const emailCheckRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const { validEmail } = this.state;
this.setState({ emailAddress: email });
if (!validEmail) {
if (emailCheckRegex.test(email)) {
this.setState({ validEmail: true });
}
} else if (!emailCheckRegex.test(email)) {
this.setState({ validEmail: false });
}
}
handlePasswordChange(password){
const { validPassword } = this.state;
this.setState({ password });
if (!validPassword) {
if (password.length > 4) {
// Password has to be at least 4 characters long
this.setState({ validPassword: true });
}
} else if (password <= 4) {
this.setState({ validPassword: false });
}
}
render(){
const {formValid, validPassword} = this.state;
const showNotification = formValid ? false:true;
const background = formValid ? colors.green01 : colors.darkOrange;
const notificationMarginTop = showNotification ? 10:0;
return(
<KeyboardAvoidingView style={[{backgroundColor:background}, styles.wrapper] } behavior="padding">
<View style={styles.ScrollViewWrapper}>
<ScrollView style={styles.ScrollView}>
<Text style={styles.loginHeader}>Log In</Text>
<InputField
labelText= "Email Address"
labelTextSize={20}
labelColor={colors.white}
textColor={colors.white}
borderBottomColor={colors.white}
inputType="email"
customStyle={{marginBottom:30}}
onChangeText={this.handleEmailChange}
/>
<InputField
labelText= "Password"
labelTextSize={20}
labelColor={colors.white}
textColor={colors.white}
borderBottomColor={colors.white}
inputType="password"
customStyle={{marginBottom:30}}
/>
</ScrollView>
<View style={styles.nextButton}>
<NexArrowButton
// handleNextButton={this.handleNextButton}
handleNextButton={()=>this.props.navigation.goBack()}
/>
</View>
<View style={[styles.notificationWrapper, {marginTop:notificationMarginTop}]}>
<Notification
showNotification={showNotification}
handleCloseNotification={this.handleCloseNotification}
type="Error"
firstLine="Those credentials don't look right."
secondLine="Please try again."
/>
</View>
</View>
</KeyboardAvoidingView>
)
}
}
const styles = StyleSheet.create({
wrapper:{
display:'flex',
flex:1,
},
ScrollViewWrapper:{
marginTop:60,
flex:1,
},
ScrollView:{
paddingLeft:30,
paddingRight:30,
paddingTop:10,
flex:1,
},
loginHeader:{
fontSize:34,
color:colors.white,
fontWeight:'300',
marginBottom:40,
},
nextButton:{
position:'absolute',
right:20,
bottom:20,
},
notificationWrapper:{
position: 'absolute',
bottom:0,
zIndex:9
}
});
The most confusing part is that the second snippet below of Login.js works perfectly and it is essentially the same thing which means that I am getting the props right, but still get the error in customised back button.
Second working snippet
<View style={styles.nextButton}>
<NexArrowButton
// handleNextButton={this.handleNextButton}
handleNextButton={()=>this.props.navigation.goBack()}
/>
</View>
App.js
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import LoggedOut from './src/screens/LoggedOut';
import LogIn from './src/screens/LogIn';
import LoggedIn from './src/screens/LoggedIn';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
const RootStack = createStackNavigator(
{
LoggedOut: LoggedOut,
LogIn: LogIn,
},
{
initialRouteName: 'LoggedOut',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
The error in more details
I really appreciate your help ! I am happy to provide more code if it makes it easier to debugg.
You have to change the static navigationOptions to following snippet if you want to access navigation properties in a static function:
static navigationOptions = ({ navigation }) => ({
headerLeft: () => (
<Button
onPress={()=>navigation.goBack()}
title="cancel"
color={colors.black}
/>
),
});
You don't need the this.props in this case ;) The static function does not have access to the this context so this.props will not work.
I wrote a snapshot test for a screen called NewUser.js, here is the test code:
import React from "react";
import NewUser from "../app/screens/NewUser/NewUser"
import renderer from "react-test-renderer"
describe("<NewUser/>", ()=>{
it("snapshot", ()=>{
expect(renderer.create(<NewUser/>).toJSON()).toMatchSnapshot();
});
});
And here is the NewUser.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
import styles from './Styles'
export default class NewUser extends Component {
static navigationOptions = () => {
return {
headerStyle: styles.headerStyle,
headerTintColor: '#fff',
headerTitle: 'JetSet',
headerTitleStyle: {
flex: 1,
}
};
};
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.background}>
<View style={styles.container}>
<Button
onPress={() => navigate('Survey', { survey: 'NewUserQuestions' })}
title="New User"
/>
</View>
</View>
);
}
}
I got the error when I run the test. What should I do to make test runnable? Thanks.
I somehow solved it by doing this
{ navigation } = this.props
...navigation.navigate()
I am still not sure the reason caused that issue, and the solution is not perfect, but it saved my code.
I'm new programing with React Native and I got this issue with my code, I'm try to do a Splash screen and after that I want to make a Login that redirect me to another screen.
The Splash screen run well but when I'm in the Login Screen and I push the "Entrar" button, it crashes and shows the message.
`
import React from 'react';
import { Image, Text, View } from 'react-native';
import { Asset, SplashScreen } from 'expo';
import Splash from './screens/Splash';
import Login from './screens/Login';
import ForgotPass from './screens/ForgotPass';
import Home from './screens/Home';
App.js
export default class App extends React.Component
{
componentWillMount()
{
this.setState({
view: <Splash />
})
setTimeout(() => {
this.setState({
view: <Login />
})
}, 3000)
}
render()
{
return(
this.state.view
)
}
}
////////////////////////////////////////////////////////////
Login.js
import React from 'react';
import { View, BackHandler } from 'react-native';
import { Card, Button, FormLabel, Text, FormInput } from 'react-native-elements';
import { createStackNavigator, navigate } from 'react-navigation';
export default class Login extends React.Component
{
static navigationOptions = {
title: 'Iniciar sesión',
headerLeft: null,
}
componentDidMount()
{
BackHandler.addEventListener('hardwareBackPress', function()
{
return true;
});
}
render()
{
return (
<View style={{ paddingVertical: 20 }}>
<Card>
<FormLabel>Nombre de Usuario</FormLabel>
<FormInput placeholder='NombreUsuario' />
<FormLabel>Contraseña</FormLabel>
<FormInput secureTextEntry placeholder='Contraseña' />
<Button
buttonStyle={{ marginTop: 20 }}
backgroundColor='#03A9F4'
title='Entrar'
onPress={() => this.props.navigation.navigate('Home')}
/>
</Card>
<View style={{ paddingVertical: 20 }}>
<Button
title="¿Olvidó su contraseña?"
onPress={() => this.props.navigation.navigate('ForgotPass')}
/>
</View>
</View>
);
}
}`
you have to pass navigation props in App.js file
componentWillMount()
{
this.setState({
view: <Splash />
})
setTimeout(() => {
this.setState({
view: <Login navigation={this.props.navigation} />
})
}, 3000)
}
or you can use withNavigation in Login.js file
import { withNavigation } from 'react-navigation';
export Default withNavigation(Login);
https://reactnavigation.org/docs/en/with-navigation.html this link will help you to learn more about withNavigation in react navigation
i am using drawer from native base for my react native application. when u click the menu button the drawer not open up and i get this error ( _this._drawer.open ) is not a fucntion what is the isse here is my code
import React, { Component } from 'react';
import {
AppRegistry,View
} from 'react-native';
import {ScrollableTab,TabHeading, Drawer, Container,Content, Header,
Title, Button, Left, Right, Body, Icon ,Text,Tab, Tabs } from 'native-base';
import SecondStatus from './component/StatusComponent';
import HeaderComponent from './component/headerComponent';
import Sports from './component/Sports';
import MainPage from './component/MainPage';
import SideBar from './component/SideBar';
export default class Point extends Component {
closeDrawer = () => {
this.drawer.close()
};
openDrawer = () => {
alert('asasa click');
console.log('asad--');
this._drawer.open();
};
render() {
return (
<Container>
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar />}
onClose={() => this.closeDrawer()} >
<Header >
<Left>
<Button transparent onPress={this.openDrawer}>
<Icon name='arrow-back' />
</Button>
</Left>
<Body>
<Title>UrduPoint</Title>
</Body>
<Right>
<Button transparent onPress=
{this.openDrawer.bind(this)}>
<Icon name='menu' />
</Button>
</Right>
</Header>
</Drawer>
</Container>
);
}
}
AppRegistry.registerComponent('Point', () => Point);
here is my SideBar.js
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet
} from 'react-native';
export default class SideBar extends Component{
render(){
return(
<View>
<Text>
asad
</Text>
</View>
)
};
}
ps. this drawer is same as in npm 'react-native-drawer'
According to the native base documentation, you should call:
this.drawer.root.open()
I have used react-native-drawer this npm thats work for me
Here is a very basic working example using native-base
import React, { Component } from 'react';
import {
Container,
Header,
Left,
Button,
Icon,
Body,
Title,
Right,
Content,
Drawer,
Text
} from 'native-base';
import {
StyleSheet,
View,
ScrollView
} from 'react-native';
class SideBar extends Component {
render() {
return (
<Container>
<Content
bounces={false}
style={{ flex: 1, backgroundColor: '#fff', top: -1 }}
>
<Button transparent>
<Text>Action</Text>
</Button>
</Content>
</Container>
);
}
}
export default class Core extends Component {
openDrawer() {
this._drawer._root.open();
}
closeDrawer() {
this._drawer._root.close();
}
render() {
return (
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar navigator={this._navigator} />}
onClose={() => this.closeDrawer()}
>
<Container>
<Header>
<Left>
<Button
transparent
onPress={() => this.openDrawer()}
>
<Icon name='menu' />
</Button>
</Left>
<Body>
<Title>TITLE</Title>
</Body>
<Right />
</Header>
<Content>
</Content>
</Container>
</Drawer>
);
}
}
Here is the sample example of NativeBase Drawer provided in its docs with a note saying You need to create your own SideBar component and import it.
Drawer Sample Code
import React, { Component } from 'react';
import { Drawer } from 'native-base';
import SideBar from './yourPathToSideBar';
export default class DrawerExample extends Component {
render() {
closeDrawer = () => {
this.drawer._root.close()
};
openDrawer = () => {
this.drawer._root.open()
};
return (
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this.navigator} />}
onClose={() => this.closeDrawer()} >
// Main View
</Drawer>
);
}
}
Check for Sidebar Sample Code from NativeBase-KitchenSink
this._drawer._root.open()
is working for me