I have been on this for a little while and here is whats going on. I have an array in mobx Storage that I Would like to display in a collapsable view within a Flatlist in my React native component. The problem here is that when I click on it it does change the state but the action does not take place. After some research, I found an Accordion in NativeBase and tried implementing it after a successful small test. Unfortunately, it does not recognize indexed values from the array saying that it is not an object. So the first issue is related to the action of closing and opening the collapsable in relation to a mobx action, the second is an accordion that is unable to read indexed values from the array. If anyone can help find a way to have a dynamic collapsable for the concerned objects within the array as well as display the values, that would be great.
Below are the concerned shunk of code, if you need more please feel free to ask, Thank you for your time!
mobx file:
import {observable, action} from 'mobx';
import {LayoutAnimation} from 'react-native'
class StateStorage {
@observable list= ['Category','','','']
@observable selectedMaterial=''
@observable materials = [
{
Specs:[
textCategory= 'Drain',
textSpec1='Usabley',
textSpec2='Healthy',
textSpec3='Bio'],
name: 'RYTT',
price: '$',
image: require("./Icons/Rain.jpg"),
spec1:require("./Icons/friendly.png"),
spec2:require("./Icons/Cutler.png"),
spec3:require("./Icons/logout.png"),
category:'',
icon: '',
uses:[
uses1='cecec',
uses2='- Cans' ,
uses3='- Jars',
uses4='- Signages',
pros:[
pros1='Lightweight',
pros2='Tough',
pros3='xsxxs',
pros4='cdccd',
],
cons:[
cons1='Inflated',
cons2='Can be sticky',
cons3='ejhcejccjhc',
cons4='dcd',
cons5='dc'],
expanded: true,
specCount:0,
userCount:0,
prosCount:0,
consCount:0,
x:0
},
{
Specs:[
textCategory= 'Drain',
textSpec1='Usabley',
textSpec2='Healthy',
textSpec3='Bio'],
name: 'RYTT',
price: '$',
image: require("./Icons/Rain.jpg"),
spec1:require("./Icons/friendly.png"),
spec2:require("./Icons/Cutler.png"),
spec3:require("./Icons/logout.png"),
category:'',
icon: '',
uses:[
uses1='cecec',
uses2='- Cans' ,
uses3='- Jars',
uses4='- Signages',
pros:[
pros1='Lightweight',
pros2='Tough',
pros3='xsxxs',
pros4='cdccd',
],
cons:[
cons1='Inflated',
cons2='Can be sticky',
cons3='ejhcejccjhc',
cons4='dcd',
cons5='dc'],
expanded: true,
specCount:0,
userCount:0,
prosCount:0,
consCount:0,
x:0
},
{
Specs:[
textCategory= 'Drain',
textSpec1='Usabley',
textSpec2='Healthy',
textSpec3='Bio'],
name: 'RYTT',
price: '$',
image: require("./Icons/Rain.jpg"),
spec1:require("./Icons/friendly.png"),
spec2:require("./Icons/Cutler.png"),
spec3:require("./Icons/logout.png"),
category:'',
icon: '',
uses:[
uses1='cecec',
uses2='- Cans' ,
uses3='- Jars',
uses4='- Signages',
pros:[
pros1='Lightweight',
pros2='Tough',
pros3='xsxxs',
pros4='cdccd',
],
cons:[
cons1='Inflated',
cons2='Can be sticky',
cons3='ejhcejccjhc',
cons4='dcd',
cons5='dc'],
expanded: true,
specCount:0,
userCount:0,
prosCount:0,
consCount:0,
x:0
},
]
@action incrementSpecCount(){
//x=uses1 or x=pros1 oe x=cons1
for (i = 0; i < this.materials.length; i++)
{
for (n=0; n<this.materials[i].Specs.length; n++){
if(this.materials[i].Specs[n]==='')
{this.materials[i].specCount++,
this.materials[i].x=i+1}}
}
}
@action incrementUserCount(){
//x=uses1 or x=pros1 oe x=cons1
for (i = 0; i < this.materials.length; i++)
{
for (n=0; n<this.materials[i].uses.length; n++){
if(this.materials[i].uses[n]==='')
{this.materials[i].userCount++,
this.materials[i].x=i+1}}
}
}
@action incrementProsCount(){
//x=uses1 or x=pros1 oe x=cons1
for (i = 0; i < this.materials.length; i++)
{
for (n=0; n<this.materials[i].pros.length; n++){
if(this.materials[i].pros[n]==='')
{this.materials[i].prosCount++,
this.materials[i].x=i+1}}
}
}
@action incrementConsCount(){
//x=uses1 or x=pros1 oe x=cons1
for (i = 0; i < this.materials.length; i++)
{
for (n=0; n<this.materials[i].cons.length; n++){
if(this.materials[i].cons[n]==='')
{this.materials[i].consCount++,
this.materials[i].x=i+1}}
}
}
@action changeLayout(index) {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.materials[index].expanded= !this.materials[index].expanded
console.log(this.materials[index].expanded)
}
React file with customized collapsable (I have removed styling positions and other values except for display due to character limit):
import React, { Component } from 'react';
import { View, Text, FlatList, Image, ImageBackground, PixelRatio, Platform, UIManager, TouchableOpacity, LayoutAnimation } from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen'
import DropDownItem from 'react-native-drop-down-item';
import StateStorage from '../StateStorage';
import {observer} from 'mobx-react';
import { Container, Header, Content, Accordion } from "native-base";
class App extends Component {
constructor (props) {
super(props)
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
componentDidMount(index){
console.log(StateStorage.materials[0].x)
console.log(StateStorage.materials[0].prosCount)
}
SpecViewStyle(index){
StateStorage.incrementSpecCount()
if(StateStorage.materials[index].specCount=== StateStorage.materials[index].x*0)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 200 : 260}}
else if(StateStorage.materials[index].specCount=== StateStorage.materials[index].x)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 185 : 200}}
else if(StateStorage.materials[index].specCount=== StateStorage.materials[index].x*2)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 165 : 150}}
else if(StateStorage.materials[index].specCount=== StateStorage.materials[index].x*3)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 130 : 120}}
}
CommonUseViewStyle(index){
StateStorage.incrementUserCount()
if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*0)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 200 : 190}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 185 : 175}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*2)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 165 : 150}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*3)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 130 : 120}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*4)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 110 : 100}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*5)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 75 :65}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*6)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 37.5 : 31}}
else if(StateStorage.materials[index].userCount=== StateStorage.materials[index].x*10
|| StateStorage.materials[index].userCount=== StateStorage.materials[index].x*9
|| StateStorage.materials[index].userCount=== StateStorage.materials[index].x*8
||StateStorage.materials[index].userCount=== StateStorage.materials[index].x*7
)
{return {height:25}}
else {return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 167.5 : 45}}
}
ProsViewStyle(index){
StateStorage.incrementProsCount()
if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*0)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 200 : 190}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 185 : 175}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*2)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 165 : 150}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*3)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 130 : 120}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*4)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 110 : 100}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*5)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 75 :65}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*6)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 37.5 : 31}}
else if(StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*8
|| StateStorage.materials[index].prosCount=== StateStorage.materials[index].x*7
)
{return {height:25}}
}
ConsViewStyle(index){
StateStorage.incrementConsCount()
if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x*0)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 200 : 190}}
else if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x)
{return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 185 : 175}}
else if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x*2)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 165 : 150}}
else if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x*3)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 130 : 120}}
else if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x*4)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 110 : 100}}
else if(StateStorage.materials[index].consCount=== StateStorage.materials[index].x*5)
{return{height:PixelRatio.get()<=2 && Platform.OS==='android' ? 75 :65}}
else {return {height:PixelRatio.get()<=2 && Platform.OS==='android' ? 200 : 190}}
}
render() {
return (
// Remain Category image and CSS
// add search bar
<View
style={{
backgroundColor:'#262A2C',
flex:1
}}>
<FlatList
style={{marginTop:80,}}
//ListHeaderComponent=
//if slow change initialNumToRender and count algorithm for use,pros and cons high
/*onEndReachedThreshold={2}
onEndReached={({ distanceFromEnd }) => {
console.log('on end reached ', distanceFromEnd)
}}*/
windowSize={StateStorage.materials.length+4}
initialNumToRender={StateStorage.materials.length}
data={StateStorage.materials}
renderItem={({ item, index }) => (
<View>
<TouchableOpacity
onPress={() =>{
StateStorage.chooseMaterial(index),
console.log(StateStorage.materials[index].count),
console.log(StateStorage.materials.length) ,
console.log(StateStorage.materials[0].x)
}}>
<ImageBackground
// read computed
source={item.image}
//pay FlatIcon or design personal one
style={{
resizeMode: 'cover',
//resizeMode: 'contain,
position:'relative',
width: wp('100%'),
left: wp('0%'),
borderBottomWidth: 1,
borderBottomColor: 'grey',
padding: hp('6%'),
}}
>
<View
style={{
flex:1,
height: null,
width: null,
borderBottomColor: 'grey',
}}>
<Image
style={{
width:wp('10%'),
height:hp('5%'),
left:wp('-10%'),
top:hp('-5.5%'),
}}
source={item.spec1}/>
<Image
style={{
width:wp('10%'),
height:hp('5.5%'),
left:wp('-10%'),
top:hp('0%'),
}}
source={item.spec2}/>
<Image
style={{
width:wp('10%'),
height:hp('5.5%'),
left:wp('-10%'),
top:hp('6%'),
}}
source={item.spec3}/>
<Text
style={{ fontWeight: 'bold',
fontSize: 22,
left:item.name.length<=5 ? wp('32.5%'):wp('27.5%'),
top:hp('-9.5%'),
}}>
{item.name}
</Text>
<Text
style={{
fontWeight: 'bold',
fontSize: 25,
top: hp('-25%'),
left:wp('80%')
}}>
{item.price}
</Text>
</View>
</ImageBackground>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0.8}
onPress={() => {
StateStorage.changeLayout(index)
console.log(StateStorage.materials[index].expanded)
}}
style={{ padding: 10,
backgroundColor:'black',
left:wp('-10.9%'),
top:hp('0%'),
width: wp('120%'),
height:hp('5%')}}>
<Image
style={{
width:wp('9%'),
height:hp('4.5%'),
tintColor:'white',
left:250,
top:-10
}}
source={StateStorage.materials[index].expanded ? require('../Icons/arrowDown.png') : require('../Icons/arrowUp.png') }/>
</TouchableOpacity>
<View style={{height: StateStorage.materials[index].expanded ? null : 0,
overflow: 'hidden',
backgroundColor:'black' }}>
<Text
style={{
fontSize: 17,
left:150,
top:-10,
color: 'turquoise',
padding: 10}}>
Specs
</Text>
<View style={this.SpecViewStyle(index)}>
<View style={{
display:item.Specs[0]==='' ? 'none' : 'flex',
}} >
<Image
style={{
display: item.Specs[0]==='' ? 'none' : 'flex',
}}
source={item.spec3}/>
<Text
style={{
display:item.Specs[0]==='' ? 'none' : 'flex',
}}>
{item.Specs[0]}
</Text>
</View>
<View style={{
display:item.Specs[1]==='' ? 'none' : 'flex',
}}>
<Image
style={{width:wp('8.5%'),
height:PixelRatio.get()<= 2 ? hp('5.5%') : hp('4%'),
display: item.Specs[1]==='' ? 'none' : 'flex',
marginBottom: 15,
tintColor:'white'}}
source={item.spec1}/>
<Text
style={{
display: item.Specs[1]==='' ? 'none' : 'flex',
}}>
{item.Specs[1]}
</Text>
</View>
<View style={{
display:item.Specs[2]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.Specs[2]==='' ? 'none' : 'flex',
}}
source={item.spec2}/>
<Text
style={{
display: item.Specs[2]==='' ? 'none' : 'flex',
}}>
{item.Specs[2]}
</Text>
</View>
<View style={{
display:item.Specs[3]==='' ? 'none' : 'flex',
}}>
<Image
display: item.Specs[3]==='' ? 'none' : 'flex',
}}
source={item.spec3}/>
<Text
style={{
,
display:item.Specs[3]==='' ? 'none' : 'flex',
}}>
{item.Specs[3]}
</Text>
</View>
<Image
//category implementation
/>
<Text>
</Text>
</View>
<Text
style={{
fontSize: 17 ,
left:125,
top:-90,
color: 'turquoise',
paddingTop: PixelRatio.get()<= 2 && Platform.OS ===' android' ? 55 :65,
paddingBottom: 10}}>
Common uses
</Text>
<View style={
this.CommonUseViewStyle(index)
}>
<Text
style=
{{
}}>
{item.uses[0]}
</Text>
<Text
style={{
display:item.uses[1]==='' ? 'none' : 'flex',
}
}
>
{item.uses[1]}
</Text>
<Text
style={{
display:item.uses[2]==='' ? 'none' : 'flex',
} }
>
{item.uses[2]}
</Text>
<Text
style={{
display:item.uses[3]==='' ? 'none' : 'flex',
} }
>
{item.uses[3]}
</Text>
</View>
<Text
style={{
}}>
Pros
</Text>
<View
style={
this.ProsViewStyle(index)
}>
<Image
style={{
display: item.pros[0]==='' ? 'none':'flex',
}}
source = {require('../Icons/plus.png')}/>
<Text
style={{
display: item.pros[0]==='' ? 'none':'flex',
}}
>
{item.pros[0]}
</Text>
<Image
style={{
display: item.pros[1]==='' ? 'none':'flex',
source = {require('../Icons/plus.png')}/>
<Text
style={{
display: item.pros[1]==='' ? 'none':'flex',
}}>
{item.pros[1]}
</Text>
<Image
style={{
display: item.pros[2]==='' ? 'none':'flex',
}}
source = {require('../Icons/plus.png')}/>
<Text
style={{
display: item.pros[2]==='' ? 'none':'flex',
}}>
{item.pros[2]}
</Text>
<Image
style={{
display: item.pros[3]==='' ? 'none':'flex',
}}
source = {require('../Icons/plus.png')}/>
<Text
style={{
display: item.pros[3]==='' ? 'none':'flex',
}}>
{item.pros[3]}
</Text>
</View>
<Text
style={{
fontSize: 17 ,
left:168,
top:-35,
marginTop:70,
color: 'turquoise',
paddingTop: PixelRatio.get()<= 2 && Platform.OS ===' android' ? 55 :65,
paddingBottom: 10
}}>
Cons
</Text>
<View style={
this. ConsViewStyle(index)
}>
<View
style={{
display:item.cons[0]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.cons[0]==='' ? 'none':'flex',
}}
source = {require('../Icons/minus.png')}/>
<Text
style={{
display: item.cons[0]==='' ? 'none':'flex',
}}
>
{item.cons[0]}
</Text>
</View>
<View
style={{
display:item.cons[1]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.cons[1]==='' ? 'none':'flex',
}}
source = {require('../Icons/minus.png')}/>
<Text
style={{
,
display: item.cons[1]==='' ? 'none':'flex',
}}>
{item.cons[1]}
</Text>
</View>
<View
style={{
display:item.cons[2]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.cons[2]==='' ? 'none':'flex',
}}
source = {require('../Icons/minus.png')}/>
<Text
style={{
display: item.cons[2]==='' ? 'none':'flex',
10,
left:60
}}>
{item.cons[2]}
</Text>
</View>
<View
style={{
display:item.cons[3]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.cons[3]==='' ? 'none':'flex',
}}
source = {require('../Icons/minus.png')}/>
<Text
style={{
,
display: item.cons[3]==='' ? 'none':'flex',
}}>
{item.cons[3]}
</Text>
</View>
<View
style={{
display:item.cons[4]==='' ? 'none' : 'flex',
}}>
<Image
style={{
display: item.cons[4]==='' ? 'none':'flex',
}}
source = {require('../Icons/minus.png')}/>
<Text
style={{
display: item.cons[4]==='' ? 'none':'flex',
}}>
{item.cons[4]}
</Text>
</View>
</View>
</View>
</View>
)}
/>
</View>
);
}
}
export default App
For the Accordion its the same code just that rather than:
it is replaced with:
<Content>
<Accordion dataArray={StateStorage.materials} expanded={null}
animation={true}
renderContent={({ item, index }) => ( ..(displayed code)... )}>
</Text>)}/>
</Content>