I made 2 screens one home screen and 2nd edit screen I need to edit data of home screen from edit screen and save it and that data should also update in home and detail screen. How can I do this without redux or context. Can anyone tell me.
Home.js
class Home extends Component {
state = {
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
],
};
render() {
return (
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.props.navigation.navigate("Edit", item)}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() => this.props.navigation.navigate("Details", item)}
/>
</>
)}
/>
Edit.js
class ListDetails extends Component {
render() {
const listing = this.props.route.params;
return (
<View>
<Image style={styles.image} source={listing.image} />
<View style={styles.detailContainer}>
<AppTextInput value={listing.title} />
<AppTextInput value={listing.des} />
</View>
<AppButton
text="Save"
onPress={() => this.props.navigation.goBack("Home")}
/>
</View>
Details.js
const listing = this.props.route.params;
return (
<View>
<Image style={styles.image} source={listing.image} />
<View style={styles.detailContainer}>
<Text style={styles.title}>{listing.title}</Text>
<Text style={styles.des}>{listing.des}</Text>
</View>
</View>
);
You can pass a function from your home screen to setState for it in your edit screen. In case navigating to edit screen causes the home screen unmounted, you can change the navigate method to push of stack navigator (I haven't tested yet). The code now should look like:
HomeScreen.js:
onEdit=(data)=>{
setState(...);
}
...
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.props.navigation.navigate("Edit", {item, onEdit})} //use push instead if error occured
style={styles.Edit}
>
...
Edit.js
class ListDetails extends Component {
render() {
const {item:listing, onEdit} = this.props.route.params;
return (
<View>
<Image style={styles.image} source={listing.image} />
<View style={styles.detailContainer}>
<AppTextInput value={listing.title} />
<AppTextInput value={listing.des} />
</View>
<AppButton
text="Save"
onPress={() => { onEdit(...); this.props.navigation.goBack("Home");}}
/>
</View>
Related
const Screen = () => {
return (
<View style={styles.container}>
<Text style={styles.heading}>Screen Data</Text>
<View>
<FlatList
data={data}
renderItem={({item}) => (
<View>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</View>
)}
ListFooterComponent={() => <Buttons text={''} onPress={undefined} />}
/>
</View>
</View>
);
};
export default Screen;
I have created a Button component which always come at the end of flatlist which is scrollable but it gets overlap I want it to keep at end of content.
List footer component is made for that it can be any component, check docs https://reactnative.dev/docs/flatlist#listfootercomponent.
I put console.log('Hello') to my button, to testing my button is work or not (actualy im using this button for navigation), but when i try to reload my app, my console show Hello. I didn't press my button yet, but when i try to press it my console didn't show hello.
Sorry for my bad english
import React from 'react';
import {View, TouchableOpacity, Image} from 'react-native';
import s from './SFooter';
import {useNavigation} from '#react-navigation/native';
const Footer = () => {
const navigation = useNavigation();
let active = 0;
return (
<View style={s.footerWrapper}>
<View style={s.iconsWrapper}>
<View style={s.iconWrapper}>
<TouchableOpacity
onPress={(console.log('asda'), () => navigation.navigate('Home'))}>
<Image
style={s.icon}
source={require('../../assets/icon/home.png')}
/>
{active == 0 ? <View style={s.iconActive} /> : <View />}
</TouchableOpacity>
</View>
<View style={s.iconWrapper}>
<TouchableOpacity>
<Image
style={s.icon}
source={require('../../assets/icon/book.png')}
/>
{active == 1 ? <View style={s.iconActive} /> : <View />}
</TouchableOpacity>
</View>
<View style={s.iconWrapper}>
<TouchableOpacity>
<Image
style={s.icon}
source={require('../../assets/icon/newspaper.png')}
/>
{active == 2 ? <View style={s.iconActive} /> : <View />}
</TouchableOpacity>
</View>
<View style={s.iconWrapper}>
<TouchableOpacity>
<Image
style={s.icon}
source={require('../../assets/icon/user.png')}
/>
{active == 3 ? <View style={s.iconActive} /> : <View />}
</TouchableOpacity>
</View>
</View>
</View>
);
};
export default Footer;
Please do check your code twice. You cannot call any function directly onPress. what i mean to say is following
Wrong:
<TouchableOpacity
onPress={(console.log('asda'), () => navigation.navigate('Home'))}
Correct
<TouchableOpacity
onPress={() => (console.log('asda'), () => navigation.navigate('Home'))}>
I'm creating a shopping cart in react native with redux but I'm getting an error
undefined is not an object (evaluating 'this.props.items.length')
I'm following a tutorial of react redux someone suggest me to follow that tutorial to make cart,
but I'm getting that error
can someone please tell me what's going on.., below is my code
class Cart extends Component {
render() {
let addedItems = this.props.items.length ? (
<FlatList
data={this.props.items}
key={(items) => items.id.toString()}
numColumns={2}
renderItem={({ item }) => (
<View>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.subTitle} numberOfLines={1}>
Quantity: {item.quantity}
</Text>
<Text style={styles.price}>Rs {item.price}</Text>
</View>
<TouchableOpacity>
<View style={styles.buy}>
<Text>Remove</Text>
</View>
</TouchableOpacity>
</View>
)}
/>
) : (
<Text>Nothing</Text>
);
return (
<View>
<View>
<Text>You Have Ordered:</Text>
</View>
<View>{addedItems}</View>
</View>
);
}
}
const mapStateToProps = (state) => {
return {
items: state.addedItems,
};
};
try like this
let addedItems = this.props.items && this.props.items.length ? (
I am trying to make a 1:1 chat, however when I try to tap on the TextInput the KeyboardAvoidingView is not working, I am not sure if this is something with my styles or if I am not using it correctly, here you can find my snack
And this is the code:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
placeholder: 'Write a message...',
text: ''
};
}
render() {
return (
<KeyboardAvoidingView style={{flex: 1, marginTop: 20}} behavior="padding" enabled>
<View style={styles.messageView}>
<Message
message="Hi! First Message"
styleMessage={'one'}
/>
<Message
message="Hi! Second Message"
styleMessage={'two'}
/>
</View>
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
selectionColor={BLUE}
placeholderTextColor={LIGHT_GRAY}
onChangeText={(text) => this.setState({text})}
placeholder={this.state.placeholder}
value={this.state.text}
onEndEditing={() => {console.log(1+1)}}
/>
</View>
<TouchableHighlight style={styles.sendButton}>
<Ionicons name="md-send" size={25} color='#FFFFFF' style={{textAlign: 'center'}}/>
</TouchableHighlight>
</View>
</KeyboardAvoidingView>
);
}
}
in this Context you only need to change
behavior="padding"
for
behavior="height"
and it will starts working correctly on both plataforms (Android/iOS)
Personally I recommend you to use instead KeyboardAwareScrollView from react-native-keyboard-aware-scroll-view package (Link) because it let you configure easier and faster the behavior of it.
I am trying to make cards clickable and expandable, but when updating state, it occurs in all the cards . I just want to make the state change in only one card (the one on which the event occurred , in this case, a click event).
However, the state gets updated for every other cards. Currently this does work on one item but it needs to work on others too.
export default class TransactionCards extends React.Component {
constructor(props) {
super(props);
this.state = {
isHidden: true
};
}
toggleHidden() {
this.setState({
isHidden: !this.state.isHidden
});
}
renderCards() {
return this.props.data.map((card, index) => (
<View key={card.id}>
<View style={styles.dateContainer}>
<Text style={styles.dateText}>{card.time}</Text>
</View>
<Card>
<TouchableWithoutFeedback onPress={this.toggleHidden.bind(this)}>
<View>
<View>
<View style={styles.transactionContainer}>
<Image
style={styles.countryImage}
source={require("../../assets/images/us-country-icon.png")}
/>
<Text style={styles.transactionTitle}>{card.title}</Text>
<Text style={styles.transactionAmount}>{card.cost}</Text>
<Icon
name={card.transactionType == "debit" ? "log-out" : "log-in"}
type="feather"
color={card.transactionType == "debit" ? "red" : "green"}
size={18}
iconStyle={styles.transactionIcon}
/>
</View>
<View>
<Text style={styles.transactionBankDetails}>{card.bankDetails}</Text>
</View>
</View>
{/* Setting visiblity condition */}
{!this.state.isHidden && (
<View>
<Divider style={styles.CardItemDivider} />
<View display="flex" flexDirection="row" justifyContent="space-between">
<View>
<Text style={styles.transactionBankDetails}>
{card.transactionCategory}
</Text>
<Text style={styles.transactionBankDetails}>{card.accountName}</Text>
</View>
<View>
<Icon name="bell" type="feather" iconStyle={styles.transactionIcon} />
</View>
</View>
</View>
)}
</View>
</TouchableWithoutFeedback>
</Card>
</View>
));
}
render() {
return <ScrollView showsVerticalScrollIndicator={false}>{this.renderCards()}</ScrollView>;
}
}
Create a new component for card and pass required params
Do the toggleHidden function inside the Card component
then inside the file it should look like
<Card {SetYourPassedParams} />
......
You have two items connected to the same state value on the same state. If you want to separate the behaviours you have to separate the values too.