onPress doesn't detect props of touchable opacity in react native - javascript

onPress doesn't show me the id of my touchable opacity component when I press on it. He just shows me undefined.
render() {
var rows = [];
var i = 0;
while(i<5){
rows.push(<TouchableOpacity id={i} activeOpacity={0.9} onPress={() => alert(this.props.id)}>
<View>
</View>
</TouchableOpacity>);
i++;
}
return {rows}
}
I want to when I press on it, it shows the id of touchable opacity. Please help me

The component you have for this render() function would need to have a prop id for this to show an alert, but I think you are wanting to show each value of i. Due to i never going out of scope within this function (as it is var), if you attempted to just do alert(i) it would show 5 for each button, but if you use const inside the while to store the current value of i, each button will have the correct value:
while (i < 5) {
const temp = i;
rows.push(
<TouchableOpacity
id={i}
activeOpacity={0.9}
onPress={() => alert(temp)}
>
<View />
</TouchableOpacity>,
);
i++;
}
You can't use a prop you are assigning in another prop you are assigning like you were trying to do.

Related

Passing in parameters to dynamically created components React Native

let itemName;
for (let j=0; j< Object.keys(menu[location][mealTime][sectionName]).length; j++) {
itemName = Object.keys(menu[diningHall][mealTime][sectionName])[j];
if (processAllergyArr(menu[diningHall][mealTime][sectionName][itemName]['itemAllergyArr'], exclusionArr, inclusionArr)) {
if (itemName.toLocaleLowerCase().indexOf(search.toLocaleLowerCase()) != -1) {
console.log(itemName)
arrOfItems.push(
<View key={j} style={{borderWidth: 1, height: 40}}>
<TouchableOpacity
key={j}
onPress={() => {onItemClick(itemName)}}
style={{height: '100%', display: 'flex', flexDirection:'row'}}
>
Here I have a variable called itemName that I try to pass in as a parameter in a function called onPress of my touchable opacity component. My touchable opacity component is in an array of components of its kind which are then included in the return function of my component.
The problem here is that the onPress function passes in the same exact parameter into onItemClick regardless of which item is associated with the opacity button.
The console.log(itemName) will log different item names but the function in onPress will use the same exact one
I was thinking that bind may be useful in this scenario but wasn't sure of how to implement it.
The reason is you declared itemName outside of for loop.
Since you are trying to make a component, it shouldn't be used like pushing values into an array.
UI Rendering will be happen in your page and this will result in itemName being the last value of its signed value.
A way to solve this is to put itemName inside of your For-Loop
for (let j=0; j< Object.keys(menu[location][mealTime][sectionName]).length; j++) {
const itemName = Object.keys(menu[diningHall][mealTime][sectionName])[j];
if (processAllergyArr(menu[diningHall][mealTime][sectionName][itemName]['itemAllergyArr'], exclusionArr, inclusionArr)) {
if (itemName.toLocaleLowerCase().indexOf(search.toLocaleLowerCase()) != -1) {
console.log(itemName)
arrOfItems.push(
<View key={j} style={{borderWidth: 1, height: 40}}>
<TouchableOpacity
key={j}
onPress={() => {onItemClick(itemName)}}
style={{height: '100%', display: 'flex', flexDirection:'row'}}
>
Declaring inside for loop should do the trick.

Basic Beginner React-Native State Question

Hello guys I just started learning React-Native and I have a question about state.
I was practicing this concept trying to make a button that shows how many times I've pressed it.
My plan was to make a variable called clicks which will increase by 1 each time I press it and set the clickState to clicks. This is my code.
export default function App() {
const [clickState, setClicks] = useState(0)
let clicks = 0
return (
<View style = {styles.container}>
<StatusBar style="auto" />
<TouchableOpacity style={styles.button} onPress={()=>{setClicks(++clicks); console.log(clicks)}}>
<Text>Clicks : {clickState}</Text>
</TouchableOpacity>
</View>
);
}
this is the console
But apparently something is wrong and my clicks value goes random between 1 and 2 each time I click it instead of increasing by 1.
So I was curious about what I was doing wrong and why the values don't increase as I expected. I would also be glad if you showed how you would implement it if there is a better way.
Thanks guys.
You only need to update clickState, no need of variable clicks.
Also it won't rerender if we increment state value directly, so we should increment state by taking its previous state value like shown below
export default function App() {
const [clickState, setClicks] = useState(0)
return (
<View style = {styles.container}>
<StatusBar style="auto" />
<TouchableOpacity style={styles.button} onPress={()=>setClicks(prevState => prevState + 1)}>
<Text>Clicks : {clickState}</Text>
</TouchableOpacity>
</View>
);
}

Missing something about how a function works? (at least for JavaScript)

function App() {
const [state, setTextState] = useState("Press the button!");
// this is the variable I want to output incremented by 1
// each time the button has been pressed
let i = 0;
return (
<View>
<Text>{state}</Text>
<Button
onPress={() => setTextState(`The button has been pressed ${++i} time(s)`)}
title={"Button 1"}
/>
</View>
);
}
The outputs sequence is something like this:
initial - The button has been pressed 0 time(s)
1 - The button has been pressed 1 time(s)
2 - The button has been pressed 2 time(s)
3 - The button has been pressed 1 time(s)
4 - The button has been pressed 2 time(s)
If the function really cannot contain variable outside of his "state", how come the {i} variable still is reachable and incremented (twice-only, but still incremented).
You can't use i as you did (as explained in this comment). You might want to look into the useRef hook for future reference as it's a good way to have persist variable throughout the lifetime of your component.
However, based on the example you provided, I'd highly recommend that you just use the state:
function App() {
const [buttonCount, setButtonCount] = useState(0);
return (
<View>
<Text>The button has been pressed {buttonCount} time(s)</Text>
<Button
onPress={() => setButtonCount(prevButtonCount => prevButtonCount + 1)}
title={"Button 1"}
/>
</View>
);
}

How to render something in an if statement React Native

Problem
I am using a flatlist in react native, and want to compare to variables in the flatlist, and render a text component if the two variables are equal, but render nothing if they are not. I've tried many methods of doing this, but they nothing has worked. I would love some help figuring out a way to do this! Thank you.
Couple ways that spring to mind straight away. Ill just assume what you are trying to compare but you can switch these variables out for whatever you please. First thing you could do is have your text be conditional inside of your Text component, EG
<Text>{this.state.variable == this.props.stuff ? "RENDER TEXT" : ""}</Text>
or, if you want to emit the Text component when variables are not equal, have a function inside of your class that will return the Text component conditionally
renderMessage = () => {
if(this.state.variable == "stuff"){
return(
<Text>They were equal</Text>
);
}else{
return(
<View></View> // OR WHATEVER YOU WANT HERE
);
}
}
...
//Then in your render function
....
<View style = {styles.whatever}>
{this.renderMessage()}
</View>
just compare your data in renderItem method accordingly
<FlatList
data={this.props.data}
renderItem={this._renderItem}
/>
_renderItem = ({item}) => (
if(item=='somthing'){
return <Text> your test </Text>
}else{
return <Text>some other text</Text>
}
);
if you want to compare your text in component then
<View>
{
item.data == 'somthing'
?
<Text>if</Text>
:
<Text>else</Text>
}
</View>

FlatList item doesn't update when I setState()

I'm building multiple select modal. When user press the item, the item should be marked as 'Checked'.
Problem I added/removed id from id arrays. When I open and check modal, it doesn't show 'Check' sign. But when I close and open the modal again, it shows 'Check' Sign.
To keep track of selected items, I defined the items in the modal component's state.
state = {
selectedSeasonIds: this.props.selectedSeasonIds,
}
Here is react-native-modal which I use to show modal on the screen
<Modal
isVisible={isSelectorVisible}
onBackdropPress = {() => this.props.hideSelector()}>
<View style={styles.modalContainer}>
<FlatList
style={styles.root}
data={this.props.items}
ItemSeparatorComponent={this._renderSeparator}
keyExtractor={this._keyExtractor}
renderItem={this._renderItemForMultiple}/>
</View>
</Modal>
This is render function for each item
_renderItemForMultiple = ({item}) => {
return (
<TouchableOpacity
style={styles.itemStyle}
onPress={() => {this._handleMultipleItemPress(item.id)}}>
<RkText>{item.value}</RkText>
{ this._renderCheck(item.id) } <<< Here is the problem
</TouchableOpacity>
);
}
When user clicks the item, FlatList's item calls _handleMultipleitemPress
_handleMultipleItemPress = (id) => {
let { selectionType } = this.props;
let { selectedSeasonIds, selectedSizeIds, selectedColorIds } = this.state;
if(selectionType===2) {
if(_.includes(this.state.selectedSeasonIds, id)) {
let newSelectedSeasonIds = _.filter(this.state.selectedSeasonIds, (curObject) => {
return curObject !== id;
});
this.setState({selectedSeasonIds : newSelectedSeasonIds});
} else {
let newSelectedSeasonIds = [...this.state.selectedSeasonIds, id];
this.setState({selectedSeasonIds : newSelectedSeasonIds});
}
}
// season Select Action
this.props.seasonSelectAction(id);
}
Problem We added/removed id from id arrays. When I open and check modal, it doesn't show 'Check' sign. But when I close and open the modal again, it shows 'Check' Sign.
Somehow the modal is not rendered even eventhough we setState in renderCheck(). Why is it happening? And How can I fix it?
_renderCheck = (id) => {
let { selectionType, selectedSeasonIds, selectedSizeIds, selectedColorIds } = this.props;
if(selectionType===2) {
if(_.includes(this.state.selectedSeasonIds, id)) {
return (<RkText>Check </RkText>);
}
}
return (<RkText> </RkText>);
}
Any other advice will be also appreciated! Thanks for reading this post.
UPDATE I debugged with code and when I press the item, it doesn't go through _renderItemForMultiple. I think it's because I didn't define a param for _renderItemForMultiple. How can I pass item to its param? Any idea?
Even though your state changes, you're not passing it to <FlatList>, so its props don't change. Its shouldComponentUpdate method returns false when none its props change. As the docs state:
By passing extraData={this.state} to FlatList we make sure FlatList itself will re-render when the state.selected changes. Without setting this prop, FlatList would not know it needs to re-render any items because it is also a PureComponent and the prop comparison will not show any changes.
So you need to pass extraData={this.state} to FlatList.

Categories