Using 'navigation' in 'cardview - javascript

I have a screen with card views.
Each card view has:
1x picture
1x title
1x description
1x touchable opacity
I was hoping to figure out a way that each touchable opacity has different navigation.
Item 0 will have navigation to screen x, the item 1 will have navigation to screen y.
My doubt is it possible to have different functions for each touchable opacity ?
function ServiceCoverageButtong() {
const navigation = useNavigation();
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate('GeneralInformationSupportScreen')}>
<Text style={styles.buttonText}>Teste</Text>
</TouchableOpacity>
</View>
);
}
const CardItemNewsProvider = ({item, index}) => {
return (
<View style={styles.container} key={index}>
<Image source={item.imgUrl} style={styles.image} />
<Text style={styles.header}>{item.title}</Text>
<Text style={styles.body}>{item.body}</Text>
<ServiceCoverageButtong />
</View>
);
};
How can I create several functions and use the item of CardItemNewsProvider?
I am new to React Native and I am struggling with doing that.
Thanks :)

Yes it's possible. You can pass a prop to your <ServiceCoverageButtong state={"0"}/>
And in your ServiceCoverageButtong() get the state from your props and run a check on what should be returned.
function ServiceCoverageButtong({state}) {
const navigation = useNavigation();
if (state == "0") {
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate('GeneralInformationSupportScreen')}>
<Text style={styles.buttonText}>Teste</Text>
</TouchableOpacity>
</View>
);
}
} else {
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate('anotherScreen')}>
<Text style={styles.buttonText}>Teste</Text>
</TouchableOpacity>
</View>
);
}
}

If you use one component for your buttons, you can just add onPress prop to your DataNewsProvider
let DataNewsProvider = [
{
title: NewsHomeCountryTitle,
body: NewsHomeCountryBody,
imgUrl: Images.newsYourCountryImage,
textButton: NewsTextButton,
onPress: () => navigation.navigate('GeneralInformationSupportScreen'),
},
{
title: NewsWorldwideTitle,
body: NewsWorldwideBody,
imgUrl: Images.newsWorldwideImage,
textButton: NewsTextButton,
onPress: () => navigation.navigate('anotherScreen'),
},
];
And pass it to your button components TouchableOpacity
const CardItemNewsProvider = ({item, index}) => {
return (
<View style={styles.container} key={index}>
<Image source={item.imgUrl} style={styles.image} />
<Text style={styles.header}>{item.title}</Text>
<Text style={styles.body}>{item.body}</Text>
<ServiceCoverageButtong state={item.stateButton} onPress={item.onPress}/>
</View>
);
};
This way you don't need to have additional conditions, and you just pass those functions as it is.

Thanks caslawter!
For anyone interested.
function ServiceCoverageButtong({state}) {
const navigation = useNavigation();
if (state === '0') {
console.log('state', state);
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() =>
navigation.navigate('GeneralInformationSupportScreen')
}>
<Text style={styles.buttonText}>Hi I'm a test</Text>
</TouchableOpacity>
</View>
);
} else {
console.log('state', state);
return (
<View>
<TouchableOpacity
style={styles.button}
onPress={() => navigation.navigate('anotherScreen')}>
<Text style={styles.buttonText}>You're really into testing</Text>
</TouchableOpacity>
</View>
);
}
}
const CardItemNewsProvider = ({item, index}) => {
return (
<View style={styles.container} key={index}>
<Image source={item.imgUrl} style={styles.image} />
<Text style={styles.header}>{item.title}</Text>
<Text style={styles.body}>{item.body}</Text>
<ServiceCoverageButtong state={item.stateButton} />
</View>
);
};
And another snipet:
let DataNewsProvider = [
{
title: NewsHomeCountryTitle,
body: NewsHomeCountryBody,
imgUrl: Images.newsYourCountryImage,
textButton: NewsTextButton,
stateButton: '0',
},
{
title: NewsWorldwideTitle,
body: NewsWorldwideBody,
imgUrl: Images.newsWorldwideImage,
textButton: NewsTextButton,
stateButton: '1',
},
];

Related

React Native Modal is not hiding

I am implementing my own Modal, trying to replace the Alert.alert with something more beautiful. I made it to be displayed when needed, but it is not hiding on the button press, but I think I transferred it the needed function. My modal structure is the following:
export const RCModal = ({ title, visible, onButtonPress }) => {
return (
<Modal
animationType='fade'
transparent={true}
visible={visible}
>
<View style={styles.container}>
<Text style={styles.title}>{title}</Text>
<Pressable style={styles.button} onPress={onButtonPress}>
<Text style={styles.text}>OK</Text>
</Pressable>
</View>
</Modal>
)
};
And it is used in the application in the following way:
// ...
const [alertVisible, setAlertVisible] = useState(false);
const [alertTitle, setAlertTitle] = useState();
const [alertOnPress, setAlertOnPress] = useState();
// ...
const winner = (theWinner) => {
setBlocked(true);
setAlertTitle(`${theWinner} win!`);
setAlertOnPress(() => setAlertVisible(!alertVisible));
setAlertVisible(true);
}
// ...
return (
<View style={styles.container}>
<RCModal title={alertTitle} visible={alertVisible} onButtonPress={alertOnPress} />
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
<Text style={styles.title}>Noughts and Crosses</Text>
<Text style={styles.tip}>Get {winCondition()} in row, column or diagonal</Text>
<View style={styles.buttonsContainer}>
<Text style={styles.turnContainer}>Turn: <Text style={[styles.turn, { color: turn === 'X' ? '#2E86C1' : '#E74C3C'}]}>{turn}</Text></Text>
<TouchableHighlight underlayColor="#000000" style={[styles.button, styles.newGameButton]} onPress={setInitialFieldState}>
<Text style={styles.buttonText}>New game</Text>
</TouchableHighlight>
</View>
<Field state={fieldState} size={fieldSize} onCellPress={onCellPress} />
</ScrollView>
<View style={styles.settingsButtonContainer}>
<TouchableHighlight underlayColor={theme.colors.secondary} style={styles.settingsButton} onPress={onSettingsPress}>
<Image source={require('../img/settings.png')} style={styles.settingsIcon} />
</TouchableHighlight>
</View>
</View>
);
};
When the winner() is called, it is displayed as it should, but when I press OK button, it is not hiding. How can I fix it?
You can use setAlertVisible to change the alertVisible state:
<RCModal title={alertTitle} visible={alertVisible} onButtonPress={() => setAlertVisible(false)} />
The answer was that to set a function like a state variable, I needed to set it like
setAlertOnPress(() => () => setAlertVisible(false))
(2 x () =>)

How can I change a button when I select a item in a flatlist

I saw some questions about it here on SO, but none of them work for me.
So my problem is when I click on the button "Add Friend" all of the buttons change to "remove", and I want to change only the button that I click
Normal
When I click in any button, all of them change to "remove"
My Code is:
export default class Friends extends Component {
state = {
visible: false,
userInfo: null,
requested: null
}
buttonAdd() {
if (this.state.requested === null) {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => this.setState({ requested: true })}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
} else if (this.state.requested === true) {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.remove, styles.removeBig]} onPress={() => this.setState({ requested: false })} >
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
} else {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => this.setState({ requested: true })}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
}
}
render() {
const inform = this.props.info
return (
<View>
<FlatList
data={inform}
keyExtractor={item => item.id.toString()}
ListHeaderComponent={this.topComponents()} //ignore this //with the ListHeaderComponent the components will not repeat
renderItem={({ item }) => (
<View style={styles.peopleContainer}>
<TouchableOpacity onPress={() => this.setState({ visible: true, userInfo: item })}> <Image source={item.photo} style={styles.photo} />
</TouchableOpacity>
<View style={styles.geralContent}>
<Text style={styles.name}>{item.name}</Text>
{this.buttonAdd()}
</View>
</View>
)}
/>
</View>
);
}
}
Sorry about the huge code.
There may be several approaches to handle this. This is just my approach to handle this specific issue.
Currently, all of the items sharing the same state. That means if any of the items update the component state, it will affect all the items of the FlatList. To overcome this problem we need to refactor the code so every item has its own state. Here is a snippet of how to do that and fix the problem
const FriendItem = ({ item, onPressPhoto }) => {
const [requested, setRequested] = React.useState(false)
return (
<View style={styles.peopleContainer}>
<TouchableOpacity onPress={() => onPressPhoto({ visible: true, userInfo: item })}>
<Image source={item.photo} style={styles.photo} />
</TouchableOpacity>
<View style={styles.geralContent}>
<Text style={styles.name}>{item.name}</Text>
<View style={styles.buttonContainer}>
{!requested ?
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => setRequested(true)}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
:
null
}
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
export default class Friends extends Component {
state = {
visible: false,
userInfo: null,
}
onPressPhoto = ({ visible, userInfo }) => {
//write your logic here to handle on click
}
render() {
const inform = this.props.info
return (
<View>
<FlatList
data={inform}
keyExtractor={item => item.id.toString()}
ListHeaderComponent={this.topComponents()} //ignore this //with the ListHeaderComponent the components will not repeat
renderItem={({ item }) => <FriendItem item={item} onPressPhoto={this.onPressPhoto} />}
/>
</View>
);
}
}

How to implement a way to delete an item from a FlatList?

I am not sure how to add a delete function in a FlatList. I know I can make different components, but I want to know how to do it within this one file. I've trying to figure this out for hours, but do not know how to do.
export default function test() {
const [enteredGoal, setEnteredGoal] = useState("");
const [courseGoals, setCourseGoals] = useState([]);
const goalInput = enteredText => {
setEnteredGoal(enteredText);
};
const addGoal = () => {
setCourseGoals(currentGoals => [
...currentGoals,
{ key: Math.random().toString(), value: enteredGoal }
]);
};
const removeGoal = goalId => {
setCourseGoals(currentGoals => {
return currentGoals.filter((goal) => goal.id !== goalId);
})
}
return (
<View style={styles.container}>
<View>
<TextInput
color="lime"
style={styles.placeholderStyle}
placeholder="Type here"
placeholderTextColor="lime"
onChangeText={goalInput}
value={enteredGoal}
/>
</View>
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={styles.listItem} >
<Text style={{ color: "lime" }}>{itemData.item.value}</Text>
</View>
)}
/>
<View>
<TouchableOpacity>
<Text style={styles.button} onPress={addGoal}>
Add
</Text>
</TouchableOpacity>
</View>
</View>
);
}
You just need to modify your code a bit to handle the delete button. Since you already have delete functionality, call that function when you click the delete button. That's it.
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={{ flexDirection: "row", justifyContent: "space-between" }}>
<Text style={{ color: "lime" }}>{itemData.item.value}</Text>
<TouchableOpacity onPress={() => removeGoal(itemData.item.key)}>
<Text>Delete</Text>
</TouchableOpacity>
</View>
)}
/>;
EDIT
change your removeGoal function as below
const removeGoal = goalId => {
setCourseGoals(courseGoals => {
return courseGoals.filter(goal => goal.key !== goalId);
});
};
Hope this helps you. Feel free for doubts.

React Native - How to pass the Image from the other Component without using React Redux

The goal is to pass the State of the Photos from my CameraRoll.js (Modal) to EventCreator.js(Modal) without using the React Redux. I'm using React Native Navigation V1.
I'm wondering maybe it is possible state of photos: [] become props? Just don't know how to do it. Need help, thank you guys!
Here are my codes:
CameraRoll.js:
state = {
photos: [],
index: null,
pickedImage: null
}
getPhotos = () => {
CameraRoll.getPhotos({
first: 200,
assetType: 'All'
})
.then(res => {
this.setState({
photos: res.edges,
});
})
.catch((err) => {
console.log('Error image: ' + err);
});
};
render() {
return(
<View style={styles.container}>
<Image source={{uri: this.state.pickedImage}} style={styles.image}/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{opacity: index === this.state.index ? .5 : 1}}
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
key={index}
underlayColor='transparent'
>
<Image
style={{width: width / 3, height: width /3}}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
EventCreator.js:
render(){
return(
<View style={styles.container}>
<EventInput
titleOnChangeText={this.eventNameChangedHandler}
descriptionOnChangeText={this.eventDescriptionChangedHandler}
titleEvent={this.state.controls.eventName}
descriptionEvent={this.state.controls.eventDescription}
/>
<Image
style={styles.image}
source={"I want to pass the image here from CameraRoll.js"}
resizeMode='contain'
/>
</View>
);
}
if you mean this:
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
it just change the state value. What you should do is put an if statement on the return of cameraRoll.js:
private onPress = (img) => {
this.props.onImagePicked(img)
}
render() {
return(
<View style={styles.container}>
<Image source={{uri: this.state.pickedImage}} style={styles.image}/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{opacity: index === this.state.index ? .5 : 1}}
onPress={() => this.onPress(photos.node.image.uri))}
key={index}
underlayColor='transparent'
>
<Image
style={{width: width / 3, height: width /3}}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
And in EventCreator.js:
constructor(){
super(props);
this.state = {
pickedImg: undefined
}
}
private onImagePicked = (newImg) => {
this.setState({
pickedImg: newImg
})
}
render(){
return(
<View style={styles.container}>
<EventInput
titleOnChangeText={this.eventNameChangedHandler}
descriptionOnChangeText={this.eventDescriptionChangedHandler}
titleEvent={this.state.controls.eventName}
descriptionEvent={this.state.controls.eventDescription}
/>
<Image
style={styles.image}
source={this.props.source}
resizeMode='contain'
/>
<CameraRoll props={...} onImagePicked={this.onImagePicked}/>
</View>
);
}

How to animate a single item from Flatlist

I have a array of data which I render in flatlist in React-Native. On pressing one of the items I want it to fade away, but instead all items on the flatlist get animated and not just the one that I pressed on.
constructor(props){
super(props);
this.state = { fadeAnim: new Animated.Value(1) }
onPressButtonnotdelivered(item) {
//Alert.alert(item.name)
const animations = [
Animated.timing(this.state.fadeAnim, {
toValue: 0,
duration: 500
}),
];
Animated.sequence(animations).start()
}
render() {
return (
<View>
<FlatList
data={this.state.data}
extraData={this.state}
keyExtractor={item => item.id}
renderItem={({ item, index }) => {
return (
<Animated.View key={index} style={[styles.animatedview, {opacity: this.state.fadeAnim}]}>
<View>
<View style={[styles.button, {backgroundColor: '#E94F64'}]}>
<TouchableOpacity style={styles.buttonview}
onPress={() => {this.onPressButtonnotdelivered(item)}}>
<View style={styles.btnIcon}>
<Icon name="block" size={30} />
<Text>Not delivered</Text>
</View>
</TouchableOpacity>
</View>
</View>
</Animated.View>
);
}}
/>
</View>
);
}
You need to add one more state to your component say indexToAnimate and set it to null.
Then put one condition in style of <Animated.View>
<Animated.View
key={index}
style={[
styles.animatedview,
{
opacity:
index == this.state.indexToAnimate
? this.state.fadeAnim
: "whatever your static value is..(in integer)"
}
]}
/>
and set indexToAnimate state on onPress method of <TouchableOpacity>
<TouchableOpacity
style={styles.buttonview}
onPress={() => {
this.setState({ indexToAnimate: index }, () => this.onPressButtonnotdelivered(item));
}}
>
<View style={styles.btnIcon}>
<Icon name="block" size={30} />
<Text>Not delivered</Text>
</View>
</TouchableOpacity>
What if you add a conditional render to the renderItem like:
renderItem={({ item, index }) => {
if (index === 'id')
return(<Animated.View> ... </Animated.View>);
else
return(<View> ... </View>);
}

Categories