The below code works and when clicked takes me the loginStack Stack Navigator
<TouchableWithoutFeedback
onPress={ this.navigateToScreen('loginStack') }>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
My NavigateToScreen function looks like this
navigateToScreen = (route) => () => {
const navigationAction = NavigationActions.navigate({
routeName: route
})
this.props.navigation.dispatch(navigationAction)
}
Since I need to manage multiple stuff, I converted it to an arrow function and it doesn't work. The below code does nothing when pressed. No response at all.
<TouchableWithoutFeedback
onPress={ () => this.navigateToScreen('loginStack') }>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
How do I fix this so I can run multiple lines of code on the onPress function like given below?
<TouchableWithoutFeedback
onPress={ () => { this.navigateToScreen('loginStack')
AsyncStorage.removeItem('token')
}}>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
Your navigateToScreen function is returning another function, which in your working example is the function being called when pressed. Where you changed onPress to an arrow function, you are calling navigateToScreen but not the function it returns.
Changing it to
<TouchableWithoutFeedback
onPress={ () => {
this.navigateToScreen('loginStack')()
AsyncStorage.removeItem('token')
}}>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
should work, or you could remove the second arrow function in your navigateToScreen function so it no longer returns a function but executes the code itself
navigateToScreen = (route) => {
const navigationAction = NavigationActions.navigate({
routeName: route
})
this.props.navigation.dispatch(navigationAction)
}
I would recommend this option, but keep in mind your currently working example would no longer work in this case.
TouchableWithoutFeedback always needs to have child View component.
<TouchableWithoutFeedback onPress={ this.navigateToScreen('loginStack') }}>
<View>
<Text>Click Me</Text>
</View>
</TouchableWithoutFeedback>
Related
Sorry for the inexperience, but how do I remove an Item in Async Storage renderized in Flat List, for example:
This is my component that creates a flatlist
export default function Saved() {
const [colors, setColors] = useState([]);
useEffect(() => {
async function getStorage() {
const nomeStorage = await AsyncStorage.getAllKeys();
if (nomeStorage != null) {
setColors(nomeStorage);
}
}
getStorage();
}, [colors])
return (
<View style={styles.body}>
<FlatList
data={colors}
keyExtractor={(item) => item}
renderItem={({ item }) => <Saveds data={item} />}
/>
</View>
);
}
and this is my FlatList renderized component
export default function Saveds(props) {
return (
<View>
<View style={styles.Boxes}>
<Box color={props.data}>
<Badge
badgeStyle={styles.badge}
value={<Text style={styles.color}>{props.data}</Text>}
/>
</Box>
<TouchableOpacity style={styles.btn}>
<Icon name={'trash-outline'} color={'#FFF'} size={30} />
</TouchableOpacity>
</View>
</View>
);
}
I need one way to when I click in my TouchableOpacity, I delete the selected data in my AsyncStorage.
The name in my AsyncStorage is the same as the value, so I can delete the AsyncStorage getting the value of my props.data.
Anyone can help me?
Deleting from your async storage should be as easy as just calling AsyncStorage.removeItem(key)
I had some similar functionality in an app that I made a while ago, I attached the delete function call to the onLongPress prop of touchableOpacity:
<TouchableOpacity
onPress={() => navigation.navigate('UserScreen', data)}
onLongPress={handleLongPress}>
<View style={styles.container}>
// ...
</View>
</TouchableOpacity>
And earlier in the component, I defined a function that handles the deleting:
const handleLongPress = async () => {
// In your instance, you should be OK to replace data.key with props.data
await AsyncStorage.removeItem(data.key);
/* I then had another function that was passed in as a prop
to update another component when the deletion had taken place */
await onChange();
};
I want to pass the title of a React Native Button component into a neighbouring function. I am using React Native functional components only for this application.
Here's the component. I would like to pass the title of the button pressed by the user, which will be either 'English' or 'Arabic', into the function submitLanguageSelection so that I can then save that value into useLocalStorage(), a custom hook I wrote to handle AsyncStorage, so that the next time the user uses the app, their language choice will be persisted, and they will not be shown the ChooseYourLanguageScreen again.
All help appreciated, thank you.
const ChooseYourLanguageScreen = ({ navigation }) => {
const [saveData, storedValue, errorMessage] = useLocalStorage();
const [userSelectedLanguage, setUserSelectedLanguage] = React.useState('');
const submitLanguageSelection = () => {
//TODO: receive params from onPress
//TODO: save the data locally
//TODO: navigate to welcome screen
};
return (
<View style={styles.container}>
{errorMessage ? <Text>{errorMessage}</Text> : null}
<Text style={styles.text}>This is the Choose Your Language Screen</Text>
<View style={styles.buttons}>
<View>
<Button
title={'English'}
onPress={() => submitLanguageSelection()}
/>
</View>
<View>
<Button title={'Arabic'} onPress={() => submitLanguageSelection()} />
</View>
</View>
</View>
);
};
You can simply pass it to the function
<Button title={'Arabic'} onPress={() => submitLanguageSelection('Arabic')} />
And access like below
const submitLanguageSelection = (language) => {
console.log(language);
};
Getting data from a sibling component is an anti-pattern.
The source of the knowledge of the language options is the ChooseYourLanguageScreen component (as seems from your snippet), so it should hold the list of available languages. Having that, you can just iterate through them and render the appropriate components:
<View style={styles.buttons}>
{languages.map((language) => (
<View key={language}>
<Button
title={language}
onPress={() => submitLanguageSelection(language)}
/>
</View>
))}
</View>
i had this issue where i'm trying to make sure the parent's onPress is triggered, but it wont
im trying to create a custom touchableOpacity component that able can be reusable, that wrap other Component so it can decide if the children can be shown or not and decide/alter what happen when the children component is pressed.
const CustomTouchable = (children, onPress) => {
function handleOnPress = () => {
if(validation){
onPress();
}
}
return <TouchableOpacity onPress={handleOnPress}>{children}</TouchableOpacity>
}
const MainComponent = () => {
function onPress = () => {console.log('test')}
<CustomTouchable onPress={onPress}>
<TouchableOpacity style={styles.button}>
<Text>Press Here</Text>
</TouchableOpacity>
</CustomTouchable>
}
but the parent onPress is not triggered, how can i trigger it?
This is because the touch event is received by the children and not the parent. Assign following prop to your Child Component
pointerEvents={"none"}
Make the second TouchableOpacity disabled like this
<TouchableOpacity onPress={onPress}>
<TouchableOpacity
disabled
style={styles.button}
>
<Text>Press Here</Text>
</TouchableOpacity>
</TouchableOpacity>
first, sorry for my bad English. I'm coding a function and have error: Maximum update depth exceeded here is error image
This is code cause error:
I have an arrow function that will change state value after touchable onPress
toggleEdit = () => {
setTimeout(() => {
this.setState({
isEdit: !this.state.isEdit
})}, 150 )
}
This is Render function :
render() {
return (
<View style={styles.body}>
<View style={styles.headerTitle}>
<View>
<TouchableOpacity onPress={this.buttonLeft}>
<Icon
name="chevron-left"
type="evilicon"
color="#FFFFFF"
size={calcScale(62)}
/>
</TouchableOpacity>
</View>
<View>
<Text style={styles.titleFont}>
{constQuotes.constQuoteAmount.label_title}
</Text>
</View>
<View style={{marginLeft: 'auto', marginRight: calcScale(17)}}>
<TouchableOpacity onPress={this.toggleEdit}>
<Text style={styles.titleAction}>
{!this.state.isEdit ? `Edit` : `Cancel`}
</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
When I call toggleEdit with onPress={this.toggleEdit}, function run ok,
But I call that with onPress={this.toggleEdit()}:
<View style={{marginLeft: 'auto', marginRight: calcScale(17)}}>
<TouchableOpacity onPress={this.toggleEdit()}>
<Text style={styles.titleAction}>
{!this.state.isEdit ? `Edit` : `Cancel`}
</Text>
</TouchableOpacity>
</View>
I have error Maximum update depth exceeded
What is difference between two ways ? Why did I have that error ?
Please help me, tks so much!
EDIT: Your error is because you're creating a loop with your onPress.
When I call toggleEdit with onPress={this.toggleEdit}, function run
ok, But I call that with onPress={this.toggleEdit()}:
This is a key point of how javascript works. Your first example is the correct one. It essentially says "when I press this, run the function this.toggleEdit()" The second example is "when I press this, run the function that this.toggleEdit() returns". In your particular case, toggleEdit() doesn't return a function; it causes an effect. And because everything within render() gets run any time any effect happens, the function will run forever.
As a side note: (original answer)
Remember that state updates may be asynchronous. Because you're updating state within your setState call, you need to use the function form.
toggleEdit = () => {
setTimeout(() => {
this.setState(state => {
isEdit: !state.isEdit
})}, 150 )
}
When you call this.toggleEdit() your call your function directly : at each render toggleEdit is executed, and you have a lifecycle loop, but when if you call your function without parenthesis you pass into TouchableOpacity props to your function so it's executed once. If it's not very clear I suggest you doc official documentation : https://reactnative.dev/docs/handling-touches.
replace
onPress={this.toggleEdit()}
by
onPress={()=>this.toggleEdit()}
In second case you are calling function in-place. You are not passing a function but the value returned by it and because that function is responsibe for rendering, infinite loop occurs.
In first case you are passing that function to onPress to execute it later when event happens.
<TouchableOpacity
style={{backgroundColor: '#FF00FF'}}
onPress={this.inputField}
>
<UselessTextInput
multiline = {true}
numberOfLines = {4}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</TouchableOpacity>
The function onPress call is:
inputField() {
console.log('Clicked')
}
i can't find any solution y its not working
i tried changing onPress to onPress={() => { console.log('Clicked') }}
it still didn't work
Can anyone tell me y its not working what i m doing wrong in it
try passing an arrowed function to the onClick prop, otherwise it won't be executed when you click on it, there are two different ways which lead to the same result :
first (in the function declaration) :
inputField = () => {
console.log('Clicked')
}
second (in the onPress prop) :
onPress={() => this.inputField}
Try adding () to the this.inputField, like the code:
onPress={()=>{this.inputField()}}