Hi there I am trying to follow tutorial but it gives this check render method error. I am making Cart for shopping app
Here is CartScreen:
import React from 'react';
import { View, Text, FlatList, Button, StyleSheet } from 'react-native';
import { useSelector } from 'react-redux';
import Colors from '../../constants/Colors';
import CartItem from '../../components/shop/CartItem';
const CartScreen = props => {
const cartTotalAmount = useSelector(state => state.cart.totalAmount);
const cartItems = useSelector(state => {
const transformedCartItems = [];
for (const key in state.cart.items) {
transformedCartItems.push({
productId: key,
productTitle: state.cart.items[key].productTitle,
productPrice: state.cart.items[key].productPrice,
quantity: state.cart.items[key].quantity,
sum: state.cart.items[key].sum
});
}
return transformedCartItems;
});
return (
<View style={styles.screen}>
<View style={styles.summary}>
<Text style={styles.summaryText}>
Total:{' '}
<Text style={styles.amount}>${cartTotalAmount.toFixed(2)}</Text>
</Text>
<Button
color={Colors.accent}
title="Order Now"
disabled={cartItems.length === 0}
/>
</View>
<FlatList data={cartItems}
keyExtractor={item => item.productId}
renderItem={itemData => (
<CartItem
quantity={itemData.item.quantity}
title={itemData.item.productTitle}
amount={itemData.item.sum}
onRemove={() => {}}
/>
)}
/>
</View>
);
};
const styles = StyleSheet.create({
screen: {
margin: 20
},
summary: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
padding: 10,
shadowColor: 'black',
shadowOpacity: 0.26,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 8,
elevation: 5,
borderRadius: 10,
backgroundColor: 'white'
},
summaryText: {
fontSize: 18
},
amount: {
color: Colors.primary
}
});
export default CartScreen;
And Here is my CartItem Component :
import React from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Platform
} from 'react-native';
import { Ionicons } from 'react-native-vector-icons';
const CartItem = props => {
return (
<View style={styles.cartItem}>
<View style={styles.itemData}>
<Text style={styles.quantity}>{props.quantity} </Text>
<Text style={styles.mainText}>{props.title}</Text>
</View>
<View style={styles.itemData}>
<Text style={styles.mainText}>${props.amount.toFixed(2)}</Text>
<TouchableOpacity onPress={props.onRemove} style={styles.deleteButton}>
<Ionicons
name={'ios-trash'}
size={23}
color="red"
/>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
cartItem: {
padding: 10,
backgroundColor: 'white',
flexDirection: 'row',
justifyContent: 'space-between',
marginHorizontal: 20
},
itemData: {
flexDirection: 'row',
alignItems: 'center'
},
quantity: {
color: '#888',
fontSize: 16
},
mainText: {
fontSize: 16
},
deleteButton: {
marginLeft: 20
}
});
export default CartItem;
I have copy paste the component inside the cart screen it works but as a component it does not work what should I do ?
What could be wrong here ?
Image of Error
I think you can try to change the way import your icons
import { Ionicons } from 'react-native-vector-icons';
It should be
import Ionicons from 'react-native-vector-icons/Ionicons'
Related
i showing some value list description and images on home screen using Flatlist .when i onpress Flatlist item passing image source and id .value passing getparams but error was TypeError: navigation.getParam is not a function.why??. Please solve issue and edit my code . i am a new to react native please solve my issue.
import React from 'react';
import { StyleSheet, Text, View, FlatList, TouchableOpacity, Image } from 'react-native';
import { Card, Rating } from 'react-native-elements'
import { MaterialCommunityIcons } from '#expo/vector-icons';
import { dishesData } from './DishesData';
const MenuDetailScreen = ({ navigation }) => {
const dish = dishesData.find(
(dish) => dish.id === this.navigation.getParam('id')
);
return (
<View style={styles.container}>
<Card>
<Card.Title
style={styles.titleTextStyle}>{dish.title}</Card.Title>
<Image style={{ height: 300, width: 350 }} source={{ uri: dish.imageSource }} />
</Card>
<Card>
<View style={{ flexDirection: "row" }}>
<Text style={styles.commentsTextStyle}>Comments</Text>
<View style={{ flexGrow: 1 }} />
<TouchableOpacity style={{ paddingBottom: 8 }} >
<MaterialCommunityIcons name="pencil-circle" size={40} color="blue" />
</TouchableOpacity>
</View>
<FlatList
scrollEnabled={false}
data={dish.dishDetails}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => {
return (
<View>
<Text style={styles.headerTextStyle}>{item.comment}</Text>
<Rating
readonly
imageSize={20}
startingValue={item.rating}
style={styles.ratingStyle}
/>
<Text style={styles.spacing}>- {item.author} , {item.created_by}</Text>
</View>
);
}}
/>
</Card>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingBottom: 10
},
commentsTextStyle: {
fontSize: 20,
fontWeight: 'bold',
textAlign: 'left'
},
textInputStyle: {
width: "80%",
padding: 8,
marginBottom: 8,
fontSize: 16
},
submitButtonStyle: {
alignItems: 'center',
width: "80%",
borderRadius: 5,
marginBottom: 8,
padding: 8,
fontWeight: 'bold',
backgroundColor: 'rgba(0, 0, 255, 0.6)',
color: 'black'
},
cancelButtonStyle: {
alignItems: 'center',
width: "80%",
borderRadius: 5,
marginBottom: 8,
padding: 8,
fontWeight: 'bold',
backgroundColor: 'grey',
color: 'black'
},
ratingStyle: {
alignItems: 'flex-start',
paddingBottom: 8
},
titleTextStyle: {
fontSize: 20,
textAlign: 'left'
},
textStyle: {
paddingBottom: 8
},
headerTextStyle: {
fontSize: 16,
fontWeight: 'bold',
paddingTop: 8
},
spacing: {
padding: 8
},
ratingStyle: {
alignItems: 'flex-start',
paddingTop: 8
}
});
export default MenuDetailScreen;
Error place
7 | const MenuDetailScreen = ({ navigation }) =>{
8 |
9 | const dish = dishesData.find(
> 10 | (dish) => dish.id === this.navigation.getParam('id')
11 |
12 | );
13 |
enter code here
Better way is to useNavigation and useRoute from React Navigation.
Step-by-step changes
Step 1
import { useNavigation, useRoute } from '#react-navigation/native';
Step 2
const navigation = useNavigation();
const route = useRoute();
Step 3
const { id } = route.params
Step 4 - Check if you are passing params when you navigate
Example)
onPress={() => navigation.navigate('SCREEN_NAME_HERE', {
PARAM_KEY: PARAM_VALUE
})}
Full Example
import React from 'react';
...
import { useNavigation, useRoute } from '#react-navigation/native';
/*
Navigate to this screen by
navigation.navigate('MenuDetailScreen', {
id: <ID_VALUE_HERE>
})
*/
const MenuDetailScreen = () => {
const navigation = useNavigation();
const route = useRoute();
const { id } = route.params
const dish = dishesData.find(
(dish) => dish.id === id
);
return (
...
)
}
Once you get it working, I recommend you to go over Type checking
with TypeScript for safely navigating between screens in React.
Update the MenuDetailScreen >>
const dish = dishesData.find(
(dish) => dish.id === this.navigation.getParam('id')
);
I'm learning react native and I've been trying to solve this issue for last 3 days.
I'm using EXPO, The buttons does not change the value in const [isStarted, setIsStarted] = useState(false)
The buttons titles are: "pause" and "start"
Here is my code:
import React, { useState,useEffect } from 'react';
import { View, StyleSheet, Text, Button,Alert } from 'react-native';
import { colors } from '../../utils/colors';
import { spacing } from '../../utils/sizes';
import { Countdown } from '../../components/Countdown';
import { RoundedButton } from '../../components/RoundedButton';
import {ProgressBar} from 'react-native-paper';
export const Timer = ({ focusSubject }) => {
const [isStarted, setIsStarted] = useState(false);
return (
<View style={styles.container}>
<View style={styles.countdown}>
<Countdown isPaused={!isStarted}/>
</View>
<View styles={{ paddingTop: spacing.xxl }}>
<Text style={styles.title}> Focusing on: </Text>
<Text style={styles.task}> {focusSubject} </Text>
</View>
<View style= {styles.buttonWrapper}>
{isStarted ? (
**<RoundedButton title="pause" onPress={() => setIsStarted(false)} />**
) : (
**<RoundedButton title="start" onPress={() => setIsStarted(true)} />**
)}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
title: {
color: colors.white,
textAlign: 'center',
},
task: {
color: colors.white,
textAlign: 'center',
fontWeight: 'bold',
},
countdown: {
flex: 0.5,
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
alignItems: 'center',
flex: 0.3,
padding: 15,
justifyContent: 'center',
},
});
You need to pass a prop name to RoundedButton component and inside of that you need to call onPress
for ex:
import React, { useState,useEffect } from 'react';
import { View, StyleSheet, Text, Button,Alert } from 'react-native';
import { colors } from '../../utils/colors';
import { spacing } from '../../utils/sizes';
import { Countdown } from '../../components/Countdown';
import { RoundedButton } from '../../components/RoundedButton';
import {ProgressBar} from 'react-native-paper';
export const Timer = ({ focusSubject }) => {
const [isStarted, setIsStarted] = useState(false);
const onButtonPress = () => {
setIsStarted(!isStarted)
}
return (
<View style={styles.container}>
<View style={styles.countdown}>
<Countdown isPaused={!isStarted}/>
</View>
<View styles={{ paddingTop: spacing.xxl }}>
<Text style={styles.title}> Focusing on: </Text>
<Text style={styles.task}> {focusSubject} </Text>
</View>
<View style= {styles.buttonWrapper}>
<RoundedButton title={isStarted ? "pause" : "start"} onButtonHandler={onButtonPress} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
title: {
color: colors.white,
textAlign: 'center',
},
task: {
color: colors.white,
textAlign: 'center',
fontWeight: 'bold',
},
countdown: {
flex: 0.5,
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
alignItems: 'center',
flex: 0.3,
padding: 15,
justifyContent: 'center',
},
});
Here I added a button handler as a prop into RoundedButton, now inside RoundedButton call onPress={onButtonHandler} in the touchable event.
If you are still facing trouble please share update RoundedButton component code
I'm trying to pass the 'data' to other archive (CampaignList.js > Campaign.js) but I don't now why the variable is not pass to Campaign.js function. I watched some videos on YouTube and read some forums and nothing help.
CampaignList.js
import React from 'react';
import {
StyleSheet,
Dimensions,
View,
Text,
TouchableOpacity,
FlatList
} from 'react-native';
import Campaign from './Campaign';
var deviceWidth = Dimensions.get('window').width;
var deviceHeight = Dimensions.get('window').height;
const App: () => React$Node = () => {
return (
<>
<View style={styles.screen}>
<FlatList
style={styles.scroll}
contentContainerStyle={{ paddingHorizontal: 20 }}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
data={[
{
id: 1,
name: 'Peregrino da Alvorada'
}
]}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => <Campaign data={item} />}
/>
<TouchableOpacity>
<View style={styles.button}>
<Text style={styles.text}>ADICIONAR CAMPANHA</Text>
</View>
</TouchableOpacity>
</View>
</>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
flexDirection: 'column'
},
scroll: {
marginHorizontal: deviceWidth * 0.05,
marginVertical: deviceHeight * 0.025,
height: deviceHeight * 0.6,
borderWidth: 1,
borderColor: 'black'
},
button: {
marginHorizontal: deviceWidth * 0.05,
marginVertical: deviceHeight * 0.025,
width: deviceWidth * 0.9,
height: deviceHeight * 0.1,
backgroundColor: '#6a0301',
alignItems: 'center',
justifyContent: 'center'
},
text: {
color: 'white',
fontWeight: 'bold'
}
});
export default App;
My idea is pass the data to here to create a query with RealmDB but the MetroServer returt an error "Can't find variable: Name" in the Campaign.js:
Campaign.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
export default function Campaign({ data }) {
return (
<View>
<Name>{data.name}</Name>
<Id>{data.id}</Id>
</View>
);
}
const styles = StyleSheet.create({
name: {
fontSize: 50,
color: 'black'
},
id: {
fontSize: 10,
color: 'grey'
}
});
You should be using Text for displaying your text components, or else you can create two different components named Name and Id ( not at all required in this use case) to display the items
import React from 'react';
import {View, StyleSheet,Text} from 'react-native';
export default function Campaign({ data }) {
return(
<View>
<Text>{data.name}</Text>
<Text>{data.id}</Text>
</View>
);
}
const styles = StyleSheet.create({
name: { fontSize: 50, color: 'black' },
id: { fontSize: 10, color: 'grey' },
});
In the original question, you were trying to use undefined components Name and Id.
I'm using react-navigation version 5, currently, I have a screen with Text and Button inside a View which placed at the top of the SafeAreaView, and I need to add TopTabNavigator just below the View.
Here's the code:
TimelineComponent.js
import React from 'react';
import PropTypes from 'prop-types';
import {ScrollView, Text} from 'react-native';
class TimelineComponent extends React.PureComponent {
render() {
return (
<ScrollView>
<Text>Timeline</Text>
</ScrollView>
);
}
}
export default TimelineComponent;
TrendingComponent.js
import React from 'react';
import PropTypes from 'prop-types';
import {ScrollView, Text} from 'react-native';
class TrendingComponent extends React.PureComponent {
render() {
return (
<ScrollView>
<Text>Trending</Text>
</ScrollView>
);
}
}
export default TrendingComponent;
TopNav.js
import React from 'react';
import {createMaterialTopTabNavigator} from '#react-navigation/material-top-tabs';
import TimelineComponent from '../TimelineComponent';
import TrendingComponent from '../TrendingComponent';
const Tab = createMaterialTopTabNavigator();
export function TopNav() {
return (
<Tab.Navigator>
<Tab.Screen name="Timeline" component={TimelineComponent} />
<Tab.Screen name="Trending" component={TrendingComponent} />
</Tab.Navigator>
);
}
WallFragmentComponent.js
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/FontAwesome';
import {
Keyboard,
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';
import {TopNav} from './TopNav';
const styles = StyleSheet.create({
container: {
padding: 20,
},
header_container: {
backgroundColor: 'white',
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
},
header_text: {
fontSize: 30,
fontWeight: '500',
},
new_chat_button: {
alignItems: 'center',
borderColor: 'blue',
borderWidth: 1,
borderRadius: 12,
display: 'flex',
flexDirection: 'row',
paddingHorizontal: 22,
paddingTop: 6,
paddingVertical: 6,
},
top_nav: {
marginVertical: 20,
},
});
class WallFragmentComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
input: {},
secureTextEntry: true,
};
}
handleInput = (name, value) => {
this.setState({
input: {...this.state.input, [name]: value},
});
};
render() {
return (
<View style={{backgroundColor: 'white'}}>
<SafeAreaView>
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
accessible={false}>
<View style={styles.container}>
<View style={styles.header_container}>
<Text style={styles.header_text}>Wall</Text>
<TouchableOpacity style={styles.new_chat_button}>
<Icon name="comment" style={{marginEnd: 6, color: 'blue'}} />
<Text style={{fontWeight: '500', color: 'blue'}}>
New Post
</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
<View style={styles.top_nav}>
<TopNav />
</View>
</SafeAreaView>
</View>
);
}
}
export default WallFragmentComponent;
In the WallFragmentComponent.js file, I have placed <TopNav /> inside a View, but it's not rendering when I run the project. Here's the screenshot:
screenshot
How am I able to add top navigation just under the Wall Text and New Post button? any help will be much appreciated.
Thank you,
Regards
This might help
// TopNav.js
const Tab = createMaterialTopTabNavigator();
const AppNavigator = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Timeline" component={TimelineComponent} />
<Tab.Screen name="Trending" component={TrendingComponent} />
</Tab.Navigator>
)
}
export default AppNavigator;
WallFragmentComponent.js
import AppNavigator from './AppNavigator';
...........
const TopNav = createAppContainer(AppNavigator);
class WallFragmentComponent extends React.PureComponent {
......
render() {
return (
<View style={{backgroundColor: 'white'}}>
......
<TopNav />
......
</View>
);
}
}
You can also use react-native-scrollable-tab-view
Well, finally I have found the solution:
Change the first <View ... /> element into <SafeAreaView style={{flex: 1}} /> and then everything is working correctly.
WallFragmentComponent.js
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/FontAwesome';
import {
Keyboard,
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';
import {TopNav} from './TopNav';
const styles = StyleSheet.create({
container: {
padding: 20,
},
header_container: {
backgroundColor: 'white',
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
},
header_text: {
fontSize: 30,
fontWeight: '500',
},
new_chat_button: {
alignItems: 'center',
borderColor: 'blue',
borderWidth: 1,
borderRadius: 12,
display: 'flex',
flexDirection: 'row',
paddingStart: 22,
paddingEnd: 22,
paddingTop: 6,
paddingBottom: 6,
},
top_nav: {
marginTop: 20,
},
});
class WallFragmentComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
input: {},
secureTextEntry: true,
};
}
handleInput = (name, value) => {
this.setState({
input: {...this.state.input, [name]: value},
});
};
render() {
return (
<SafeAreaView style={{flex: 1, backgroundColor: 'white'}}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={styles.container}>
<View style={styles.header_container}>
<Text style={styles.header_text}>Wall</Text>
<TouchableOpacity style={styles.new_chat_button}>
<Icon name="comment" style={{marginEnd: 6, color: 'blue'}} />
<Text style={{fontWeight: '500', color: 'blue'}}>
{' '}
New Post
</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
<TopNav />
</SafeAreaView>
);
}
}
export default WallFragmentComponent;
Screenshot
And that's it
I was trying to make a "photo galley app" where each image is a "button" that toggle on the boolean property for Modal tag. The problem is that the images are rendered by a FlatList which pass props to component "GenerateImage.js", but at the same time, I need to pass the state and dispatch function as a parameter as well.
File who render the FlatList:
import React, { Component } from 'react'
import { FlatList, View, StyleSheet, TouchableOpacity, Text, AppRegistry } from 'react-native'
import { connect } from 'react-redux'
import GenerateImage from '../components/GenerateImage'
import commonStyles from '../commonStyles'
import Modal from '../components/Modal'
const Photos = ({ params }) => {
return (
<View style={{ flex: 1 }}>
<Modal isVisible={params.showFullImage} />
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Hoje</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Mês</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Ano</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Álbuns</Text>
</TouchableOpacity>
</View>
<View style={{ flex: 30 }}>
<FlatList data={params.images} keyExtractor={item => `${item.id}`}
renderItem={({item}) => <GenerateImage {...item} />} numColumns={2} />
</View>
</View>
)
}
const styles = StyleSheet.create({
buttonsContainer: {
flex: 3,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#1c2431',
},
touchContainer: {
marginHorizontal: 20,
backgroundColor: '#439ce8',
borderRadius: 30,
width: 65,
alignItems: 'center',
justifyContent: 'center',
padding: 5
},
button: {
color: 'white',
fontFamily: commonStyles.Font,
fontSize: 14
}
})
export default connect(state => ({ params: state[0] }))(Photos)
GenerateImage.js:
import React from 'react'
import { View,
StyleSheet,
Image,
PixelRatio,
Dimensions,
TouchableOpacity } from 'react-native'
import { connect } from 'react-redux'
const GenerateImage = (props, {param, dispatch}) => {
function toggleModal(param) {
return {
type: 'TOGGLE_MODAL_ON',
}
}
return (
<View style={styles.container}>
<View style={styles.imgContainer}>
<TouchableOpacity activeOpacity={0.7} onPress={() => dispatch(toggleModal(param))}>
<Image source={props.image} style={styles.imgContainer} />
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginVertical: 5,
marginHorizontal: 4
},
imgContainer: {
height: Dimensions.get('window').height * 0.25,
width: Dimensions.get('window').width * 0.48,
//borderRadius: 8,
//flex: 1,
//orderWidth: 1,
},
image: {
resizeMode: 'contain',
aspectRatio: PixelRatio.get()
},
})
export default connect(state => ({ param: state[0].showFullImage }))(GenerateImage)
So, how can I pass both data?