React Native Modal is not hiding - javascript

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 () =>)

Related

Using 'navigation' in 'cardview

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',
},
];

How to add a popup modal when selecting a list item react native and show their details

As title says, I need to create a modal popup for every list item for the selected sizes to be displayed. I'm using the react-native-popup-dialog but without results. Could you help me? Here's my code:
step1 = () => {
return (
<View style={{ flex: 8}}>
<Text h3 style={{ ...styles.title, marginVertical: 10.0 }}>{this.state.user=="User"?"Size":"CargoSize"}</Text>
<ScrollView>
<View style={{ marginHorizontal: 16.0 }}>{
this.state.size.map((l, i) => (
<ListItem key={i} onPress={() => this.setState({sizeSelected: i, sizeName: l.title, sizeId: l.id})} underlayColor='transparent'
containerStyle={{backgroundColor: this.state.sizeSelected==i?'#F76858':'white', borderWidth: 1.0,
borderColor: '#707070', marginBottom: 10.0, paddingVertical: 5.0, paddingHorizontal: 40.0}}>
<ListItem.Content>
<View style={{
flexDirection: 'row', alignItems: 'center',
justifyContent: 'center'
}}>
<Text style={styles.textSize}>{l.title}</Text>
<Text style={{ fontSize: 16 }}>{l.example}</Text>
</View>
</ListItem.Content>
</ListItem>
))
}</View>
</ScrollView>
</View>
);
}
I believe you can declare a single modal in your list component and show or hide the modal when the user presses the listItem. Also, make the pressed item active and pass the item to your modal so that the modal can show the details of the active item.
App.js
export default function App() {
const [modalVisible, setModalVisible] = React.useState(false);
const [activeItem, setActiveItem] = React.useState(null);
const onPress = (item) => {
setActiveItem(item)
setModalVisible(true)
}
const renderItem = ({ item }) => (
<TouchableOpacity onPress={()=>onPress(item)}>
<Item title={item.title} />
</TouchableOpacity>
);
return (
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
<Popup modalVisible={modalVisible} setModalVisible={setModalVisible} activeItem={activeItem} />
</View>
);
}
Modal.js
export default function Popup({modalVisible, setModalVisible, activeItem}) {
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>{activeItem?.title}</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: '#2196F3' }}
onPress={() => {
setModalVisible(!modalVisible);
}}>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
Here is a working demo for you.
I made something similar in my react-native project and do this:
Made with {useState} the variables i need in my modal, example, the name of my component
Wrap the ListItem component in a Pressable component
Put the onPress={() => {//Put your code here}} function, inside you will put the SetVariable of the variable you want in the modal
The Pressable will update the variable with the wich you want in the modal

react-native how to change usestate data getting from other page?

i'm beginner of react-native. help me haha...
i give a useState data ('playlist') from MainPage.js to playList.js
in MainPage.js
const [playList, setPlayList] = useState([]);
<TouchableOpacity onPress={() => navigate('PlayList', {data: playList})}>
in playList.js
const Imagetake = ({url}) => {
url =url.replace('{w}', '100');
url = url.replace('{h}', '100');
return <Image style ={{height:'100%', width:'100%'}} source ={{url:url}}/>
};
const PlayList = ({ navigation }) => {
const playList = navigation.getParam('data');
const setPlayList = navigation.getParam('setData');
const deletePlayList = (data) => {
setPlayList(playList.filter((song)=> song.id != data.id));
};
return (
<View style={styles.posts}>
<FlatList
data={playList}
keyExtractor={posts => posts.id}
renderItem={({item}) =>{
return (
<View>
<TouchableOpacity onPress={() => deletePlayList( item )}>
<Ionicons name="trash-outline" size={30}/>
</TouchableOpacity>
<TouchableOpacity>
<View style={styles.post}>
<View style ={styles.postcontent}>
<Imagetake url={item.attributes.artwork.url}></Imagetake>
</View>
<View style={styles.posthead}>
<View style = {styles.postheadtext}>
<Text style ={styles.posttitletext}>{item.attributes.name}</Text>
<Text style={styles.username}>{item.attributes.artistName}</Text>
</View>
<View style = {styles.postheadtext2}>
<Text style={styles.username}>{item.attributes.albumName}</Text>
</View>
</View>
</View>
</TouchableOpacity>
</View>
)
}}
/>
</View>
);
};
when i delete some songs in playList, it is well done in playList page. but when i go to mainpage and go to playList again, delete is useless. the songs that i deleted before is refreshed. how can i fix it? T^T
You may also pass the setPlayList function to PlayList page.
And instead of creating another useState in the child page, you directly call the setPlayList that is passed from parent page

Conditional rendering using data from an API in react native

So, I'm building an application that monitors foreign exchange prices. It allows a user to input a price of a selected currency pair that they would like to be alerted once the inputted price is reached. I have tried using conditional rendering to do this but am only getting alerted on the same price that i have just put in the Textinput instead of monitoring the prices. Below is the code:
//Condition
const CheckAlertCondition = () => {
if( {...currency.data.prices[clickedindex].closeoutAsk} >= pricealert )
{
return(
Alert.alert("Target reached", "Price"+ pricealert+"has been hit")
)
}
else if({...currency.data.prices[clickedindex].closeoutBid} <= pricealert) {
return(
Alert.alert("Target reached", "Price"+ pricealert+"has been hit")
)
}
return false
}
<Modal
visible={modalopen}
animationType={"fade"}
>
<View style={styles.modal}>
<View>
<Text style={{textAlign: "center", fontWeight: "bold"}}>
{currency.data.prices[clickedindex].instrument}
</Text>
<Text style={{textAlign: "center"}}>
{currency.data.prices[clickedindex].closeoutAsk}/{currency.data.prices[clickedindex].closeoutBid}
</Text>
<Card.Divider/>
<View style={{ flexDirection: "row"}}>
<View style={styles.inputWrap}>
<TextInput
style={styles.textInputStyle}
value={pricealert}
onChangeText = {(pricealert) => setPricealert(pricealert)}
placeholder="Alert Price"
placeholderTextColor="#60605e"
numeric
keyboardType='decimal-pad'
/>
</View>
<View style={styles.inputWrap}>
</View>
</View>
<TouchableOpacity
onPress={() =>
ActionSheet.show(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
title: "How do you want to receive your notification"
},
buttonIndex => {
setSheet({ clicked: BUTTONS[buttonIndex] });
}
)}
style={styles.button}
>
<Text>ActionSheet</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button}
onPress={() => {setModalOpen(false); CheckAlertCondition();showToastWithGravityAndOffset();} }>
<Text style={styles.buttonTitle}>OK</Text>
</TouchableOpacity>
</View>
</View>
</Modal>

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.

Categories