具有对象数组的React-Native ListView

时间:2017-03-04 17:04:29

标签: arrays listview reactjs object react-native

嘿,所有人都会喜欢这个问题的帮助..我一直在撕扯我的头发!

我尝试使用以下形式的对象数组来呈现ListView:

Array[number]
 0: Object
  category: ''
  date: ''
  total: ''
  vendor: ''
 1: Object ..etc.

我正在使用此处的组件react-native-swipe-list-view:swipeList github

但我只渲染数据对象数组的最后一个元素!我也在这个反应本机应用程序中使用redux,尽管我没有看到这有任何影响 救命 ! :)

输出如下 enter image description here

这是我目前的代码。

import React, {
    Component,
} from 'react';
import {
    ListView,
    Text,
    TouchableOpacity,
    TouchableHighlight,
    View,
  Alert
} from 'react-native';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { SwipeListView } from 'react-native-swipe-list-view';
import {
  PRIMARY_HIGHLIGHT_COLOUR,
  CARD_BACKGROUND_COLOUR,
  BORDER_COLOUR
 } from '../global/colours';
import {
  MySearchBar,
  Button,
  FAB,
  BackgroundView,
 } from '../components';
 import { HEADER } from '../global/margins';

class ReceiptsListView extends Component {

    constructor(props) {
        super(props);
        console.log(this.props.receiptList);
        this.ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
        this.state = {
            listViewData: this.ds.cloneWithRows(this.props.receiptList)
        };
        console.log('state', this.state);
    }


/*  shouldComponentUpdate(nextProps) {
    if (this.props !== nextProps) {
      return true;
    }
    return false;
  } */

    deleteRow(secId, rowId, rowMap) {
    //  rowMap[`${secId}${rowId}`].closeRow();
    //console.log('delete', secId, rowId, rowMap);

    //  const newData = [...this.state.listViewData];
    //  newData.splice(rowId, 1);
    //  this.setState({ listViewData: newData });
    }

    render() {
        //const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
        //const dataSource = ds.cloneWithRows(receiptlist);
        //this.ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
        return (
            <BackgroundView style={styles.container}>
                <View style={styles.search}>
                    <MySearchBar />
                    <Button style={styles.button}> Export </Button>
                </View>
                <SwipeListView
                        dataSource={this.state.listViewData}
                        renderRow={(data) => this.renderRow(data)}
                        renderHiddenRow={(secId, rowId, rowMap) => this.renderHiddenRow(secId, rowId, rowMap)}
                        rightOpenValue={-150}
                        recalculateHiddenLayout
                        previewFirstRow
                />
                <FAB
            onPress={this.onPressFAB}
                />
            </BackgroundView>
        );
    }

renderRow(data) {
        console.log('data', data);
        return (
            <TouchableHighlight
                onPress={console.log('You touched me')}
                style={styles.rowFront}
                underlayColor={'#AAA'}
            >
                <View>
                    <View style={{ flexDirection: 'row', justifyContent: 'space-between' }} >
                        <Text> {`${data.vendor}`} </Text>
                        <Text> {`${data.total}`} </Text>
                    </View>
                    <View>
                        <Text> {`${data.date}`} </Text>
                        <Text> {`${data.category}`} </Text>
                    </View>
                </View>
            </TouchableHighlight>
        );
    }

    renderHiddenRow(secId, rowId, rowMap) {
        return (
        <View style={styles.rowBack}>
            <TouchableOpacity
                style={[styles.backRightBtn, styles.backRightBtnLeft]}
                onPress={_ => (console.log(secId, rowId, rowMap))}
            >
                <Text style={styles.backTextWhite}>Export</Text>
            </TouchableOpacity>
            <TouchableOpacity
                style={[styles.backRightBtn, styles.backRightBtnRight]}
                onPress={_ => (console.log(secId, rowId, rowMap))}
            >
                <Text style={styles.backTextWhite}>Delete</Text>
            </TouchableOpacity>
        </View>
        );
    }

  onPressFAB() {
    console.log('FAB pressed');
    Alert.alert(
      'Choose Photo Source',
      null,
      [
        { text: 'Camera', onPress: () => Actions.camera() },
        { text: 'Photo Library', onPress: () => Actions.photos() },
        { text: 'Cancel', onPress: () => console.log('cancel'), style: 'cancel' }
      ]
    );
  }
}

const styles = {
  search: {
    flexDirection: 'row',
    padding: 10,
    height: 60,
    backgroundColor: PRIMARY_HIGHLIGHT_COLOUR
  },
  button: {
    marginTop: 0,
    height: 30,
    flexGrow: 0.3
  },
    container: {
    padding: 0,
    paddingTop: HEADER.height
    },
    rowFront: {
        //alignItems: 'center',
    flex: 1,
    padding: 10,
        backgroundColor: CARD_BACKGROUND_COLOUR,
        borderBottomColor: BORDER_COLOUR,
        borderBottomWidth: 1,
        justifyContent: 'center',
        //height: 100,
    },
    rowBack: {
        alignItems: 'center',
        backgroundColor: '#DDD',
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingLeft: 15,
    },
    backRightBtn: {
        alignItems: 'center',
        bottom: 0,
        justifyContent: 'center',
        position: 'absolute',
        top: 0,
        width: 75
    },
    backRightBtnLeft: {
        backgroundColor: 'blue',
        right: 75
    },
    backRightBtnRight: {
        backgroundColor: 'red',
        right: 0
    },
    controls: {
        alignItems: 'center',
        marginBottom: 30
    },
    switchContainer: {
        flexDirection: 'row',
        justifyContent: 'center',
        marginBottom: 5
    },
    switch: {
        alignItems: 'center',
        borderWidth: 1,
        borderColor: 'black',
        paddingVertical: 10,
        width: 100,
    }
};

const mapStateToProps = ({ receipts, accounts }) => {
  const {
    myReceipts,
        receiptList
  } = receipts;
  const {
    labelsArray
  } = accounts;
  return {
    myReceipts,
    receiptList,
    labelsArray
  };
};

export default connect(mapStateToProps, {
})(ReceiptsListView);

1 个答案:

答案 0 :(得分:5)

问题是flex:1在renderRow的样式中(样式。 rowFront)

以下是工作代码,因为我确信它可以对其他人有所帮助。

import React, {
    Component,
} from 'react';
import {
    ListView,
    Text,
    TouchableOpacity,
    TouchableHighlight,
    View,
  Alert,
    TextInput
} from 'react-native';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import { SwipeListView } from 'react-native-swipe-list-view';
import Icon from 'react-native-vector-icons/FontAwesome';
import Spinner from 'react-native-loading-spinner-overlay';

import {
  PRIMARY_HIGHLIGHT_COLOUR,
  CARD_BACKGROUND_COLOUR,
  BORDER_COLOUR,
    SHADOW_COLOUR
 } from '../global/colours';
import {
  Button,
  FAB,
  BackgroundView,
    TitleText
 } from '../components';
 import { HEADER } from '../global/margins';
 import { searchTextChanged, deleteReceipt } from '../actions';

class ReceiptsListView extends Component {

    constructor(props) {
        super(props);
        console.log(this.props.receiptList);
        console.log(this.props.categories);
        this.ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    }

  shouldComponentUpdate(nextProps) {
    if (this.props !== nextProps) {
      return true;
    } else if (this.props.searchQuery !== nextProps.searchQuery) {
            return true;
        }
    return false;
  }

    render() {
        if (this.props.receiptList.length < 1) {
            return (
                <BackgroundView style={styles.emptyContainer}>
                    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                        <TitleText> No Receipts </TitleText>
                    </View>
                    <FAB
                        onPress={this.onPressFAB}
                    />
                </BackgroundView>
            );
        }
        return (
            <BackgroundView style={styles.container}>
                <View style={styles.search}>
                        <View style={{ flexGrow: 1, height: 35, paddingTop: 5 }}>
                            <View style={styles.searchStyle}>
                                <View style={styles.searchbar}>
                                    <Icon
                                        name="search"
                                        size={15}
                                        color="#ddd"
                                    />
                                    <TextInput
                                        style={{ flexGrow: 1, width: null, paddingLeft: 5 }}
                                        placeholder='search'
                                        placeholderTextColor='lightgray'
                                        onChangeText={this.onSearchChange.bind(this)}
                                        value={this.props.searchQuery}
                                        onFocus={() => console.log('hi')}
                                    />
                                </View>
                            </View>
                        </View>
                        <Button
                            style={styles.button}
                            //onPress={this.searchText()}
                        >
                            Search
                        </Button>
                    </View>
                <SwipeListView
                        dataSource={this.ds.cloneWithRows(this.props.receiptList)}
                        renderRow={(data) => this.renderRow(data)}
                        renderHiddenRow={(secId, rowId, rowMap) => this.renderHiddenRow(secId, rowId, rowMap)}
                        rightOpenValue={-150}
                        recalculateHiddenLayout
                        previewFirstRow
                />
                <FAB
            onPress={this.onPressFAB}
                />
                <Spinner
                    visible={this.props.isFetching}
                    textContent={''}
                    textStyle={{ color: 'white' }}
                />
            </BackgroundView>
        );
    }

    onSearchChange(text) {
        this.props.searchTextChanged(text);
    }

    renderRow(data) {
        //console.log('data', data);
        return (
                <TouchableHighlight
                    onPress={() => console.log('You touched me', data)}
                    underlayColor={'#AAA'}
                    style={styles.rowFront}
                >
                    <View>
                        <View style={{ flexDirection: 'row', justifyContent: 'space-between' }} >
                            <Text> {`${data.vendor}`} </Text>
                            <Text> {`${data.total}`} </Text>
                        </View>
                        <View>
                            <Text> {`${data.date}`} </Text>
                            <Text> {`${data.category}`} </Text>
                        </View>
                    </View>
                </TouchableHighlight>
        );
    }

    renderHiddenRow(secId, rowId, rowMap) {
        return (
        <View style={styles.rowBack}>
            <TouchableOpacity
                style={[styles.backRightBtn, styles.backRightBtnLeft]}
                onPress={() => (this.exportItem(secId, rowId, rowMap))}
            >
                <Text style={styles.backTextWhite}>Export</Text>
            </TouchableOpacity>
            <TouchableOpacity
                style={[styles.backRightBtn, styles.backRightBtnRight]}
                onPress={() => (this.deleteItem(secId, rowId, rowMap))}
            >
                <Text style={styles.backTextWhite}>Delete</Text>
            </TouchableOpacity>
        </View>
        );
    }

    deleteItem(secId, rowId, rowMap) {
        console.log('secId', secId, 'rowId', rowId, 'rowMap', rowMap);
        console.log('obj', secId.id, 'acc', this.props.curAccountID);
        this.props.deleteReceipt(this.props.curAccountID, secId.id);
    }

    exportItem(secId, rowId, rowMap) {
        console.log('secId', secId, 'rowId', rowId, 'rowMap', rowMap);
        //this.props.exportReceipt(this.props.curAccountID, secId.id);
    }

  onPressFAB() {
    console.log('FAB pressed');
    Alert.alert(
      'Choose Photo Source',
      null,
      [
        { text: 'Camera', onPress: () => Actions.camera() },
        { text: 'Photo Library', onPress: () => Actions.photos() },
        { text: 'Cancel', onPress: () => console.log('cancel'), style: 'cancel' }
      ]
    );
  }
}

const styles = {
  search: {
    flexDirection: 'row',
    padding: 10,
    height: 60,
    backgroundColor: PRIMARY_HIGHLIGHT_COLOUR
  },
    searchbar: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingLeft: 5
    },
  button: {
    marginTop: 0,
    height: 30,
    flexGrow: 0.3
  },
    container: {
    padding: 0,
    paddingTop: HEADER.height
    },
    emptyContainer: {
        flex: 1,
        padding: 0,
        paddingTop: HEADER.height,
        justifyContent: 'center'
    },
    rowFront: {
        //alignItems: 'center',
    padding: 10,
        backgroundColor: CARD_BACKGROUND_COLOUR,
        borderBottomColor: BORDER_COLOUR,
        borderBottomWidth: 1,
        justifyContent: 'center',
        //height: 100,
    },
    rowBack: {
        alignItems: 'center',
        backgroundColor: '#DDD',
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingLeft: 15,
    },
    backRightBtn: {
        alignItems: 'center',
        bottom: 0,
        justifyContent: 'center',
        position: 'absolute',
        top: 0,
        width: 75
    },
    backRightBtnLeft: {
        backgroundColor: 'blue',
        right: 75
    },
    backRightBtnRight: {
        backgroundColor: 'red',
        right: 0
    },
    controls: {
        alignItems: 'center',
        marginBottom: 30
    },
    switchContainer: {
        flexDirection: 'row',
        justifyContent: 'center',
        marginBottom: 5
    },
    switch: {
        alignItems: 'center',
        borderWidth: 1,
        borderColor: 'black',
        paddingVertical: 10,
        width: 100,
    },
    searchStyle: {
        flex: 1,
        flexDirection: 'row',
        alignSelf: 'stretch',
        padding: 5,
        justifyContent: 'flex-start',
        alignItems: 'center',
        backgroundColor: CARD_BACKGROUND_COLOUR,
        borderRadius: 10,
        borderWidth: 1,
        borderColor: 'grey',
        marginLeft: 5,
        marginRight: 5,
        shadowColor: SHADOW_COLOUR,
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.1,
        shadowRadius: 2,
    },
};

const mapStateToProps = ({ accounts, receipts, searchIt }) => {
    const {
        curAccountID
    } = accounts;
    const {
        searchQuery
    } = searchIt;
  const {
        isFetching,
    myReceipts,
        receiptList,
        categories
  } = receipts;
  return {
        curAccountID,
        isFetching,
    myReceipts,
        receiptList,
        searchQuery,
        categories
  };
};

export default connect(mapStateToProps, {
        searchTextChanged, deleteReceipt
})(ReceiptsListView);