The menu is collapsing out but not in? - javascript

Im using the accordion-collapse-react-native library. What I have to do is, when the card is clicked and the menu is opened the arrow icon should change from arrow down to arrow up. The logic that im using is opening and changing the arrow but its not closing anymore. Can u help me to figure out why??
const [collapse, setCollapse] = useState(false);
<Collapse
style={styles.locationContainer}
isCollapsed={collapse}
onToggle={(isCollapsed) => setCollapse({ collapse: isCollapsed })}>
<CollapseHeader>
<TouchableOpacity onPress={() => setCollapse({ collapse: !collapse })}>
<Text style={styles.title}>Zgjedhni lokacionin</Text>
<View style={styles.friendsContainer}>
<View style={styles.itemsContainerLocation}>
<Text style={styles.subTitle}>Shtëpia e shokut</Text>
<Text style={styles.default}>(parazgjedhur)</Text>
</View>
{collapse ? (
<Ionicons name="ios-arrow-up" size={24} color="black" />
) : (
<Ionicons name="ios-arrow-down" size={20} color="black" />
)}
</View>
</TouchableOpacity>
</CollapseHeader>
<CollapseBody>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia ime</Text>
</View>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia e prindërve</Text>
</View>
<View style={styles.adressesContainer}>
<Text style={styles.adressesName}>Shtëpia e gjyshit</Text>
</View>
</CollapseBody>
</Collapse>

Your accordion-collapse-react-native component looks like the exemple in the doc (and this is not a reproach), the only difference is that you are using usestate hook and the exemple is a Class component so the managing state syntax change a bit.
Instead of onToggle={(isCollapsed) => setCollapse({ collapse: isCollapsed })}> try onToggle={(isCollapsed) => setCollapse( isCollapsed )}
And instead of <TouchableOpacity onPress={() => setCollapse({ collapse: !collapse })}> try <TouchableOpacity onPress={() => setCollapse( !collapse )}>

Related

React native : Flatlist inside scrollview

My goal is for this entire block to be scrollable.
I tried all kinds of ways to achieve the goal but without success.
I tried with ListHeaderComponent and moved the entire top view to it and it didn't work.
And I also tried <FlatList nestedScrollEnabled />
And it didn't work either.
What is the correct way to reach the scroll?
I come from here :
const renderAccordians = () => {
const items: JSX.Element[] = [];
areaData.forEach(item => {
items.push(<Accordian item={item} key={item.title} />);
});
return items;
};
To here :
return (
<View>
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons size={24} name={data.checked ? 'check-box' : 'check-box-outline-blank'} color={'black'} />
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'} size={30} color={'black'} />
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={false}
renderItem={({ item, index }) => (
<View>
<TouchableOpacity style={[styles.childRow, styles.button]} onPress={() => onClick(index)}>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
Since your FlatList will be part of an Accordion component, you "can't" embed the ExpandButton inside the Flatlist > ListHeaderComponent ... cause It'll simply hide the whole FlatList along with it's Header when you collapse your accorddion...
keyExtractor is also missing in your FlatList .. I added index as a key here which is not recommended BTW, you better use a unique field in your listItem like id...
return (
<View style={{ flex: 1}}> // <<--- Look here
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons
size={24}
name={data.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons
name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'}
size={30}
color={'black'}
/>
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={true} // <<--- Look here
keyExtractor={(_, index) => index.toString()} // <<=== Look here
contentContainerStyle={{flexGrow: 1}} // <<--- Look here
renderItem={({ item, index }) => (
<View>
<TouchableOpacity
style={[styles.childRow, styles.button]}
onPress={() => onClick(index)}
>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
If it does not work, I think you should create a component and use map datalist to render all the items and putting them into the ScrollView tag.
<ScrollView
style={styles.messageContain}
ref={ref => {
this.scrollView = ref;
}}
{data.data.map((item, index) => {
return <YourComponent key={index} data={item} />;
})}
</ScrollView>

How can conditional rendering for array map

I have condition for profile page
I want to show user profile data
name . age etc..So I map array to get each user data
but problem is when there is no data in firestore , this profile page is empty
this is really disappointed
I want to conditional rendering the following rendering
But error is
jsx expression must have one parent element
so how can render this correctly
return (
<SafeAreaView style={styles.container}>
{values.map((value)=>(
<React.Fragment key={value.id}>
<View style={styles.header}></View>
<Image style={styles.avatar} source={{uri : value.photo}}/>
<View style={styles.body}>
<View style={styles.bodyContent}>
<Text style={styles.name}>{value.displayName}</Text>
<View style={styles.label}>
<Text >My Job is - </Text>
<Text>{value.job}</Text>
</View>
<View style={styles.label}>
<Text>My Age is - </Text>
<Text >{value.age}</Text>
</View>
<View style={styles.label}>
<Text>My Gender is - </Text>
<Text >{value.gender}</Text>
</View>
<View style={styles.label}>
<Text>I want to meet - </Text>
<Text >{value.interestIn}</Text>
</View>
</View>
</View>
</React.Fragment>
))}
<View style={tw("p-10 flex-row items-center justify-between px-5")}>
<Pressable
style={
tw('p-3 rounded-xl bg-red-400')} onPress={goedit}>
<Text style={styles.text}>Edit Profile</Text>
</Pressable>
<Pressable
style={
tw('p-3 rounded bg-red-400')} onPress={logout}>
<Text style={styles.text}>LOGOUT</Text>
</Pressable>
</View>
</SafeAreaView>
)
I want to show user profile page as template even no data in firestore
can someone help me
Just add a <> ontop of the map and then </> on the bottom to close it. If you need flex then you can switch out the <></> for
You could try something like this, but paste your logic inside if statement:
const renderValues = () => {
values.map((value) => {
if (value) {
return (
<View>
<Text>data</Text>
</View>
);
} else {
return <View>no data</View>;
}
});
};
return <>{renderValues()}</>;
const renderValues = () => {
values.map((value) => {
if (value) {
return (
<React.Fragment key={value.id}>
<View style={styles.header} />
<Image style={styles.avatar} source={{ uri: value.photo }} />
<View style={styles.body}>
<View style={styles.bodyContent}>
<Text style={styles.name}>{value.displayName}</Text>
<View style={styles.label}>
<Text>My Job is - </Text>
<Text>{value.job}</Text>
</View>
<View style={styles.label}>
<Text>My Age is - </Text>
<Text>{value.age}</Text>
</View>
<View style={styles.label}>
<Text>My Gender is - </Text>
<Text>{value.gender}</Text>
</View>
<View style={styles.label}>
<Text>I want to meet - </Text>
<Text>{value.interestIn}</Text>
</View>
</View>
</View>
</React.Fragment>
);
} else {
return <View>no data</View>;
}
});
};
return (
<SafeAreaView style={styles.container}>
<>
{renderValues()}
<View style={tw('p-10 flex-row items-center justify-between px-5')}>
<Pressable style={tw('p-3 rounded-xl bg-red-400')} onPress={goedit}>
<Text style={styles.text}>Edit Profile</Text>
</Pressable>
<Pressable style={tw('p-3 rounded bg-red-400')} onPress={logout}>
<Text style={styles.text}>LOGOUT</Text>
</Pressable>
</View>
</>
</SafeAreaView>
);

Warning: Cannot update a component from inside the function body of a different component. in TouchableOpacity

I got this error
Warning: Cannot update a component from inside the function body of a different component.
How to fix this ?
When I remove touchable opacity, it's not showing anymore
<View style={styles.SaD}>
<TouchableOpacity onPress={(e) = props.locationSetState(1)}> // here
<Text style={styles.text1}>Choose your starting point</Text>
</TouchableOpacity>
<TouchableOpacity onPress={(e) = props.locationSetState(2)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
</View>
details are not sufficient to understand your problem but according to what I understand from your code try using react hooks and try this
function App() {
const [state,setState]=React.useState(null);
console.log(state);
return (
<View style={styles.SaD}>
<TouchableOpacity onPress={(e) => setState(1)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
<TouchableOpacity onPress={(e) => setState(2)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
</View>
);
}

Automatically scroll ScrollView in KeyboardAvoidingView when I add a new TextInput

I am working with a KeyboardAvoidingView and it's working perfectly fine except for one small issue. In the code below I have a TouchableOpacity that when clicked runs the function addName() which appends to an array and creates a new TextInput - basically when you click it, it adds a new TextInput to the ScrollView.
The KeyboardAvoidingView works perfectly fine except every time a new TextInput is added/rendered, I have to scroll down to see it. Do you know how I can make it automatically scroll to the bottom when a new TextInput is rendered?
Here is my code for the KeyboardAvoidingView:
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS == "ios" ? "padding" : "height"}
>
<HeaderComponent
name={this.props.route.params.bill.barName + " Tab"}
navigation={this.props.navigation}
goHome={true}
goHomePrompt={true}
/>
<View
style={{
marginTop: 30,
marginLeft: 10,
}}
>
<Text
style={{ color: "white", fontSize: 18 }}
allowFontScaling={false}
>
Add people to split with...
</Text>
</View>
<ScrollView keyboardShouldPersistTaps={"handled"}>
{this.state.nameInput.map((value, index) => (
<View style={styles.nameContainer} key={index}>
<View
style={{
width: "90%",
}}
>
<TextInput
style={styles.textInputContainer}
value={value}
onChange={this.handleText(index)}
placeholder={"Enter name..."}
placeholderTextColor={"#333333"}
maxLength={50}
/>
</View>
<View
style={{
width: "10%",
}}
>
<TouchableOpacity
onPress={() => this.handleDelete(index)}
>
<Icon name="cancel" type="material" color="red" />
</TouchableOpacity>
</View>
</View>
))}
<TouchableOpacity onPress={() => this.addName()}>
<Text style={styles.addPerson}>+ Add Person</Text>
</TouchableOpacity>
</ScrollView>
<View style={styles.bottomContainer}>
<TouchableOpacity
style={styles.continueButton}
onPress={() => {
// filters through array to make sure there are no empty strings
let nameInput = this.state.nameInput.filter(
(name) => name !== ""
);
if (
nameInput.length > 1 &&
new Set(nameInput).size === nameInput.length
) {
this.setState({ nameInput, loading: false });
} else {
alert(
"Please make sure there are at least two people and no duplicate names!"
);
}
}}
>
<Text style={styles.continueButtonText} allowFontScaling={false}>
Continue to Split Tab
</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
And here is my code for the addName() function:
addName = () => {
let nameInput = this.state.nameInput.concat("");
this.setState({
nameInput,
});
};
This page has the solution I was looking for: Is it possible to keep a ScrollView scrolled to the bottom?

React Native : How to call child refs from the parent's event funtion?

Have parent tag as <TouchableWithoutFeedback> and child as <Image>, trying to change the image source from the parent onPress function, but getting error. how can I archive this using refs? or any other way to resolve it?
React-native version : 0.56
Error :
Cannot read property 'favIcon' of undefined
Sample Code :
const fav = require('../../images/favorite.png');
const nonfav = require('../../images/not_favorite.png');
updateFavorite = (id) => {
this.props.refs.favIcon.source(fav);
}
render(){
return (
<View style={styles.container}>
<TouchableWithoutFeedback onPress={ this.updateFavorite.bind(this, 1) }>
<View style={ styles.imageView }>
<Image refs="favIcon" source={ nonfav } />
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={ this.updateFavorite.bind(this, 2) }>
<View style={ styles.imageView }>
<Image refs="favIcon" source={ nonfav } />
</View>
</TouchableWithoutFeedback>
</View>
)
}
Note : change only the child image of onPressed, not all images.
try it using nativeProps, like
import resolveAssetSource from 'resolveAssetSource';
this.refs['favIcon'].setNativeProps({
src: [resolveAssetSource(fav)]
});
refer this for more.
It might not work with react-native 0.50+ versions but according to this comment it should work with 0.57.1
Updating properties of elements in React is best done by calling setState method. Try the following
updateFavorite = (event) => {
event.target.setAttribute('src', fav)
}
render(){
return (
<View style={styles.container}>
<TouchableWithoutFeedback>
<View style={ styles.imageView }>
<img ref={ref => this.favIcon = ref} src={nonFav} onPress={ this.updateFavorite }/>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback>
<View style={ styles.imageView }>
<img ref={ref => this.favIcon = ref} src={nonFav} onPress={ this.updateFavorite } />
</View>
</TouchableWithoutFeedback>
</View>
)
}

Categories

Resources