I created an accordion and I created some logic for it but when I look at my code it doesn't feel right. I don't know where to ask so I'm asking here.
So I created an accordion component and Implemented it on my screen. What is specific about this accordion is that when one accordion opens other one closes. So I used useState()
that I forward as a prop to the accordion.
I was also thinking to put useState()
inside the accordion but I don't know how to close it when I click on the other accordion. So I created this.
I need tips on how to improve it or how to make it cleaner because right now when I look at the code it works but it doesn't look good.
//AccordionCompontent.js
import React from 'react'
import { StyleSheet, View, Text, Dimensions } from 'react-native';
import Collapsible from 'react-native-collapsible';
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
const Accordion = props => {
return (
<View>
<TouchableWithoutFeedback onPress={props.onPress}>
<View style={styles.accordionContainer}>
<Text style={styles.accordionContainerTitle} >{props.title}</Text>
</View>
</TouchableWithoutFeedback>
<Collapsible style={styles.accordionCollapsedContainer} collapsed={props.isCollapsed}>
{props.accordionRender}
</Collapsible>
</View>
);
}
export default Accordion;
const styles = StyleSheet.create({
accordionContainer: {
justifyContent:'center',
borderBottomWidth: 1,
borderBottomColor: '#fff',
minHeight: Dimensions.get('window').height / 15
},
accordionCollapsedContainer: {
borderBottomWidth: 1,
borderBottomColor: '#fff'
},
accordionContainerTitle: {
color: '#fff',
fontSize: 16,
marginLeft:10
},
})
//InformationScreen.js
import React, { useCallback, useLayoutEffect, useState } from 'react'
import { Text, View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons'
import BodyText from '../components/Atomic/BodyText';
import Accordion from '../components/Accordion/Accordion';
const InformationScreen = props => {
const [isCollapsed, setIsCollapsed] = useState([true, true, true, true, true])
const collapse = (id) => {
let updatetIsCollapsed = [...isCollapsed]
updatetIsCollapsed[id] = !updatetIsCollapsed[id]
const filteredUpdateIsCollapse = updatetIsCollapsed.filter((value, index) => id !== index)
filteredUpdateIsCollapse.forEach(element => {
if (!element) {
const index = filteredUpdateIsCollapse.indexOf(element)
filteredUpdateIsCollapse[index] = true
}
});
filteredUpdateIsCollapse.splice(id, 0, updatetIsCollapsed[id])
setIsCollapsed(filteredUpdateIsCollapse)
}
useLayoutEffect(() => {
props.navigation.setOptions({
title: 'Information',
headerStyle: {
backgroundColor: '#000'
},
headerTitleStyle: {
fontSize: 22,
color: '#fff'
},
headerLeft: () => (
<View></View>
),
headerRight: () => (
<TouchableWithoutFeedback onPress={() => {
props.navigation.popToTop()
}}>
<View style={styles.iconContainer}>
<Icon name="home" size={30} color={'#fff'} />
</View>
</TouchableWithoutFeedback>
)
})
})
return (
<View style={styles.container}>
<Accordion onPress={useCallback(() => {
collapse(0)
},
[isCollapsed, setIsCollapsed],
)} title={"Lorem"} isCollapsed={isCollapsed[0]} accordionRender={
<View style={styles.accordionItemContainer}>
<View style={styles.accordionItemSpacing}>
<BodyText>Lorem Ipsum</BodyText>
<BodyText>Lorem Ipsum</BodyText>
</View>
<View>
<BodyText>Lorem ipsum</BodyText>
<BodyText>Lorem ipsum</BodyText>
</View>
</View>
} />
<Accordion onPress={useCallback(() => {
collapse(1)
},
[isCollapsed, setIsCollapsed],
)} title={"Bla bla"} isCollapsed={isCollapsed[1]} accordionRender={
<View>
<Text>Test</Text>
<Text>Test</Text>
</View>
} />
<Accordion onPress={useCallback(() => {
collapse(2)
},
[isCollapsed, setIsCollapsed],
)} title={"Bla bla"} isCollapsed={isCollapsed[2]} accordionRender={
<View>
<Text>Test</Text>
<Text>Test</Text>
</View>
} />
<Accordion onPress={useCallback(() => {
collapse(3)
},
[isCollapsed, setIsCollapsed],
)} title={"Bla bla"} isCollapsed={isCollapsed[3]} accordionRender={
<View>
<Text>Test</Text>
<Text>Test</Text>
</View>
} />
<Accordion onPress={useCallback(() => {
collapse(4)
},
[isCollapsed, setIsCollapsed],
)} title={"Lorem Ipsum"} isCollapsed={isCollapsed[4]} accordionRender={
<View style={styles.accordionItemContainer}>
<View style={styles.accordionItemSpacing}>
<BodyText>Lorem Ipsum</BodyText>
<BodyText>Lorem Ipsum</BodyText>
</View>
<View>
<BodyText>Lorem ipsum</BodyText>
<BodyText>Lorem ipsum</BodyText>
</View>
</View>
} />
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#000',
flex: 1,
borderTopWidth: 2,
borderTopColor: '#fff'
}
,
iconContainer: {
height: 50,
width: 50,
borderLeftWidth: 2,
borderLeftColor: '#fff',
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'flex-end'
},
accordionContainerTitle: {
color: '#000',
fontSize: 16,
},
accordionItemContainer: {
paddingVertical: 10,
},
accordionItemText: {
color: '#000',
fontSize: 16,
marginHorizontal: 10,
},
accordionItemSpacing: {
marginBottom: 10
}
})
export default InformationScreen;