Passing in parameters to dynamically created components React Native - javascript

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.

Related

Error in styling when using function to determine flex React Native

Im trying to create 2 dropdown menus where depending on which are clicked would reduce a third view's flex number to accommodate the other 2 expanded views. Im using two useState variables to keep track of the 2 different dropdown menus, and calculate the flex as shown:
const [isFirstExpanded, setIsFirstExpanded] = useState(false)
const [isSecondExpanded, setIsSecondExpanded] = useState(false)
const calculateFlex = () => {
if (isFirstExpanded && isSecondExpanded) {
return 0; // This means both dropdowns are expanded, and should hide the third view
} else if (isFirstExpanded || isSecondExpanded) {
return 2; // Only one of the dropdowns are open, so half the size of the third view
} else {
return 4; // None of the dropdowns are open, so show the full view
}
}
<View style={{flex: 1}}>
<View style={{flex: calculateFlex, backgroundColor: "red"}}/> // View to be grown or shrunk depending on below views
<TouchableOpacity style={{flex: 1}} onPress={setIsFirstExpanded(!isFirstExpanded)}/>
<View style={isFirstExpanded ? styles.expandView : styles.hideView}/> // The dropdown that is hidden by default
<TouchableOpacity style={{flex: 1}} onPress={setIsSecondExpanded(!isSecondExpanded)}/>
<View style={isSecondExpanded ? styles.expandView : styles.hideView}/> // The dropdown that is hidden by default
</View>
This code leaves out some innocuous things, if needed I can copy/paste them. My problem occurs when the first view to be grown or shrunk doesn't seem to follow the calculate flex function. Not sure why, or if there is a better way to calculate this.

How to make a line break in textinput after insert a image component inside of it? REACT-NATIVE

im new in react-native and im doing a bloc note, the problem now is that i want to allow the user put images with the note, something like this:
my structure for this for now is this:
render() {
return (
<>
<View style = {this.styles.container}>
<TextInput style = {this.styles.TextInput_title} placeholder = "Title" multiline = {true} maxLength = {80} value = {this.state.title} onChangeText = {title => this.setState({title: title})}></TextInput>
<View style = {this.styles.textinput_container}>
<TextInput style = {this.styles.textinput} multiline = {true} onChangeText = {content => this.setState({content: content})}><Text>{this.state.content}{"\n"}</Text>
<Text>{this.state.img}</Text>
</TextInput>
<Button title = "Add image" onPress = {this.add_Image}></Button>
<Button title = "Save Changes" onPress = {this.save_Changes}></Button>
</View>
</View>
}
add_Image = () => {
this.setState({content: this.state.content + "\n\n\n"});
const img = <Image source = {require("../img/ny.png")} style = {{width: 100, height: 100}}></Image>
this.setState({img:img});
}
for now im just using a button to add the image to see if it works, but i get this:
as you can see, the pointer (the blue line) is still there and doesnt does a line break, maybe is the way that im using to do this, but like i said, im new and for now i dont know another way to do this, so if anyone can help me, really will appreciate :)
You could achieve this by some modifications to the style:
E.G:
<Text style={{ flex: 1, marginTop: '25%' }}>{this.state.img}</Text>
Where,
marginTop: Gona gives you the proportion of the space you want to leave on top.
flex: Set it on 1 it's going to put it on its on space.

React rendering another table row with click dynamic

Hey Stack OverFlow community I am working on a React project where I am mapping over a set of table rows. Within every table row I have an additional row with more info about each individuals rows data. My issue is that when I click on the button to render additional information for that table it renders all of the additional informations for all of the rows.
I understand that my logic is implemented in a way where every single additional row will show upon a click. What can I do to fix this?
https://codesandbox.io/s/rj8o4r493n
showDrawyer = () => {
let {showDrawyer} = this.state
this.setState({
showDrawyer: !showDrawyer
})
}
renderTableCellData = () => {
let { tableData } = this.props;
return tableData.map((data, index) => {
return (
<Table.Body>
<Table.Row style={{ height: 75 }}>
<Table.Cell onClick={this.showDrawyer}>{data.name}</Table.Cell>
<Table.Cell>{data.number}</Table.Cell>
<Table.Cell>{data.date}</Table.Cell>
<Table.Cell>{data.uid}</Table.Cell>
</Table.Row>
<Table.Row style={{display: this.state.showDrawyer ? '' : 'none' }}>
<Table.Cell>Hidden Row data</Table.Cell>
</Table.Row>
</Table.Body>
)
})
}
state={
shownDrawerIndex:null
}
showDrawyer = (index) => {
this.setState({
shownDrawerIndex:index
})
}
renderTableCellData = () => {
let { tableData } = this.props;
return tableData.map((data, index) => {
return (
<Table.Body>
<Table.Row style={{ height: 75 }}>
<Table.Cell onClick={()=>this.showDrawyer(index)}>{data.name}</Table.Cell>
<Table.Cell>{data.number}</Table.Cell>
<Table.Cell>{data.date}</Table.Cell>
<Table.Cell>{data.uid}</Table.Cell>
</Table.Row>
<Table.Row style={{display: this.state.shownDrawerIndex == index ? '' : 'none' }}>
<Table.Cell>Hidden Row data</Table.Cell>
</Table.Row>
</Table.Body>
)
})
}
You will have to pass the index of the row on click.This will set the state to that index.
React will re-render the component on set state. While doing this it will check for the drawer index value in state.
According to that state value, it will display and hide the drawer
The solution depends on whether you want (1) additional details to be displayed for multiple rows, or whether (2) once you click on one row, only this row's additional details will be shown, and hidden for the one clicked before.
For (1) Add to the tableData array a showDrawyer field which will be tested in order to know whether to display or not to display the additional info for this element.
OnClick should get as parameter the clicked array element and should toggle this element's showDrawyer value.
For (2) - the state variable that decides which row's additional details are displayed will be an index, rather than a toggle. This index will be checked for the additional details display.

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

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.

create multiple buttons in a view via loop

I want to create multiple custom buttons for my react-native app.
I'm using an array with all the informations in it and I want to iterate over all buttons in the array and create all buttons in one single view.
I tried something like this:
<View>
for( let i=0; i<numberButtons; i++) {
<TouchableOpacity style={[styles.mapView, this.props.mapViewStyle]} >
<Image
style={[styles.image, this.props.imageStyle]}
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
/>
</TouchableOpacity>
}
</View>
That doesn't seem to work. I get errors from the react-native framework so I guess you can't do js in a view?
How can I do this?
You can do it like this:
renderButtons = () => {
const buttons = [];
for( let i = 0; i < numberButtons; i++) {
buttons.push(
<TouchableOpacity style={[styles.mapView, this.props.mapViewStyle]}>
<Image
style={[styles.image, this.props.imageStyle]}
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
/>
</TouchableOpacity>
)
}
return buttons;
}
render() {
return (
<View>
{this.renderButtons()}
</View>
)
}

Categories