Я разрабатываю приложение для Android, используя нативную реакцию, которая включает страницу корзины. Я использовал [ExpandableListView]:https://aboutreact.com/expandable-list-view/), чтобы показать элементы, сгруппированные по категориям. У каждого элемента есть кнопки «+» и «-» для изменения количества. Вот мой код:
DetailScreen.js:
import React, { Component } from 'react';
import { LayoutAnimation, StyleSheet, TouchableOpacity, View, Text, ScrollView, UIManager, Platform, TextInput, KeyboardAvoidingView, ImageBackground, Picker, Image, Linking, Alert, } from 'react-native';
export default class DetailsScreen extends Component
{
static navigationOptions = {
title: 'Details',
header: null,
}
constructor(props)
{
super(props);
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
this.state =
{
listDataSource: [
{
isExpanded: false,
category_name: 'Item 1',
subcategory: [{ id: 1, val: 'Sub Cat 1', count:'0' }, { id: 3, val: 'Sub Cat 3', count:'0' }],
},
{
isExpanded: false,
category_name: 'Item 2',
subcategory: [{ id: 4, val: 'Sub Cat 4', count:'0' }, { id: 5, val: 'Sub Cat 5', count:'0' }],
}],
};
}
updateLayout = index => {
LayoutAnimation.configureNext
(LayoutAnimation.Presets.easeInEaseOut);
const array = [...this.state.listDataSource];
array[index]['isExpanded'] = !array[index]['isExpanded'];
this.setState(() => {
return {
listDataSource: array,
};
});
};
updateSalonData = newData =>
{
console.info('new Data: ' + JSON.stringify(newData));
var tempData = [...this.state.listDataSource];
let index = tempData.findIndex(x => x.category_name === newData.category_name);
tempData[index] = newData;
this.setState(() => {
return {
listDataSource: tempData,
};
});
};
render() {
return (
<View style = {{ marginStart: 10, marginEnd: 10, marginTop: 5, borderBottomWidth: 0.5 }}></View>
<Text style = {styles.topHeading}>Services</Text>
<ScrollView enabled keyboardShouldPersistTaps = {'handled'} showsVerticalScrollIndicator = {false} contentContainerStyle = {{ flexGrow: 1, }}>
{this.state.listDataSource.map((item, key) => (
<ExpandableItemComponent
key = {item.category_name}
onClickFunction = {this.updateLayout.bind(this, key)}
item = {item}
updateSalonData = {this.updateSalonData.bind(this, item)}/>
))}
</ScrollView>
</View>
);
}
}
ExpandableItemComponent.js:
import React, { Component } from 'react';
import { LayoutAnimation, StyleSheet, View, Text, ScrollView, UIManager, TouchableOpacity, Platform, } from 'react-native';
export default class ExpandableItemComponent extends Component {
//Custom Component for the Expandable List
constructor(props) {
super(props);
console.info('props: ' + JSON.stringify(props.item));
this.state = {
layoutHeight: 0,
dataSource:props.item,
};
}
componentWillReceiveProps(nextProps) {
console.info('componentWillReceiveProps');
if (nextProps.item.isExpanded) {
this.setState(() => {
return {
layoutHeight: null,
};
});
} else {
this.setState(() => {
return {
layoutHeight: 0,
};
});
}
console.info('next Item: ' + JSON.stringify(nextProps.item) + "\n");
this.setState(() => {
return {
dataSource: nextProps.item,
};
});
}
shouldComponentUpdate(nextProps, nextState) {
if (this.state.layoutHeight !== nextState.layoutHeight) {
return true;
}
return false;
}
setItemCount = (id) =>
{
const tempItem = this.props.item;
const data = this.props.item.subcategory;
const index = data.findIndex(x => x.id === id);
// console.info('pricing Index: ' + index);
if (index !== -1) {
data[index]["cartCount"] = 10;
tempItem.subcategory = data;
this.props.updateSalonData(tempItem);
}
}
render() {
return (
<View>
{/*Header of the Expandable List Item*/}
<TouchableOpacity
activeOpacity = {0.8}
onPress = {this.props.onClickFunction}
style = {styles.header}>
<Text style = {styles.headerText}>{this.state.dataSource.category_name}</Text>
</TouchableOpacity>
<View
style = {{
height: this.state.layoutHeight,
overflow: 'hidden',
}}>
{/*Content under the header of the Expandable List Item*/}
{this.state.dataSource.subcategory.map((item, key) => (
<TouchableOpacity
key = {key}
style = {styles.content}
onPress = {() => alert('Id: ' + item.id + ' val: ' + item.val)}>
<View style = {{ flex: 1, flexDirection: 'row', alignContent: 'center', justifyContent: 'space-between'}}>
<Text style = {styles.text}>{item.val}</Text>
<View style = {{ flexDirection: 'row', alignSelf: 'center', }}>
<Text style = {styles.text}>{item.val}</Text>
<View style = {{ height: 25, width: 75, flexDirection: 'row', borderRadius: 15, borderWidth: 1, alignSelf: 'center', justifyContent: 'space-evenly', borderColor: 'orange', overflow: 'hidden' }}>
<View style = {{ alignContent: 'center', justifyContent: 'center' }}>
<Text onPress = {()=>{this.setItemCount(item.id)}} style = {{ width: 25, height: 25, fontSize: 12, color: 'orange', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>+</Text>
</View>
<View style = {{ borderWidth: 1, borderColor: 'orange', backgroundColor: 'orange', alignContent: 'center', justifyContent: 'center' }}>
<Text style = {{ width: 25, height: 25, fontSize: 12, color: 'white', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>{item.cartCount}</Text>
</View>
<View style = {{ alignContent: 'center', justifyContent: 'center' }}>
<Text style = {{ width: 25, height: 25, fontSize: 12, color: 'orange', fontWeight: 'bold', textAlign: 'center', textAlignVertical: 'center' }}>-</Text>
</View>
</View>
</View>
</View>
{/* <View style = {styles.separator} /> */}
</TouchableOpacity>
))}
</View>
<View style = {styles.separator} />
</View>
);
}
}
Теперь проблема в том, что когда я нажимаю кнопку «+», счетчик фактически увеличивается в коде, но не обновляется в пользовательском интерфейсе. Но когда я сворачиваю и разворачиваю один и тот же элемент, теперь значение обновляется. Кто-нибудь, пожалуйста, помогите мне обновить счетчик, как только я нажму кнопку +.
Можете ли вы заменить свой this.state.dataSource, чтобы направить this.props.updateSalonData на ExpandableItemComponent.js
Если обновление было выполнено в родительском классе, оно автоматически обновится в дочернем классе, если это произойдет.
например:
...
{this.props.updateSalonData.subcategory.map((item, key) => (
....
так.