从 React Native 中的 Flatlist 数据中区分前一个元素和当前元素

问题描述 投票:0回答:4

我正在尝试使用 React Native 构建一个聊天应用程序。我正在使用 flatlist 列出对话的消息。

export default class ExampleConversation extends React.Component {
    _renderItem = ({item}) => {
        return (
            <View style={{backgroundColor: 'white', margin: 4, flexDirection: 'row'}}>
                <Text>{item.sender.id}</Text>
                <Text>{item.body}</Text>
            </View>
        )
    };

    render() {
        return <FlatList
                    data={data}
                    renderItem={this._renderItem}
                    keyExtractor={(item, id) => item.id}
                    style={styles.container}
                    inverted={true}/>
    }
}

从服务器获取的JSON数据:

const data = [
    {
        "id": 13,
        "sender_id": 1,
        "body": "Some message"
    },
    {
        "id": 12,
        "sender_id": 1,
        "body": "Some message"
    },
    {
        "id": 11,
        "sender_id": 5,
        "body": "Some message"
    }
];

从上面的数据可以看出,第一条消息和第二条消息都来自同一个发件人(

sender_id: 1
)。当上一条消息和当前消息来自同一发件人时,我想删除该消息对象的
<Text>{sender_id}</Text>

    return (
        <View style={{backgroundColor: 'white', margin: 4, flexDirection: 'row'}}>
            <Text>{item.body}</Text>
        </View>
    )

基本上,我想通过检查为 Flatlist 数据给出的元素来更改 Message 组件的布局,就像 facebook Messenger 显示其消息的方式一样。

enter image description here

如何通过 Flatlist 数据的键值区分先前元素和当前元素?

reactjs user-interface react-native react-native-flatlist
4个回答
6
投票

Flatlist 的

renderItem
属性为当前渲染项提供
index
属性。您可以使用索引来查找前一项的发件人是否相同。要实现这种行为,您需要对数据进行排序。

例如

const data = [
    {
        "id": 13,
        "sender_id": 1,
        "body": "Some message",
        "sentDate": 00003,
    },
    {
        "id": 12,
        "sender_id": 1,
        "body": "Some message"
        "sentDate": 00002,
    },
    {
        "id": 11,
        "sender_id": 5,
        "body": "Some message"
        "sentDate": 00001,
    }
];

    isSenderSame = ({currentMessage, prevMessage}) => {
      return currentMessage.sender_id === prevMessage.sender_id;
    }
    _renderItem = ({item, index}) => {
        const style = isSenderSame(item, this.state.data[(index - 1)]) ? styles.sameMessageStyle : styles.differentMessageStyle;
        return (
            <View style={[{backgroundColor: 'white', margin: 4, flexDirection: 'row'}, style]}>
                <Text>{item.sender.id}</Text>
                <Text>{item.body}</Text>
            </View>
        )
    };

    render() {
        return <FlatList
                    data={this.state.data}
                    renderItem={this._renderItem}
                    keyExtractor={(item, id) => item.id}
                    style={styles.container}
                    inverted={true}/>
    }

更新

另一种方法是让服务器对数据进行排序。您可以分块发送消息并使用循环渲染它们

renderItem

const data = [{
    "sender_id": 5,
    "messages": [{
        "id": 14,
        "body": "Some message"
        "sentDate": 00006
    }]
}, {
    "sender_id": 1,
    "messages": [{
        "id": 13,
        "body": "Some message",
        "sentDate": 00003
    }, {
        "id": 12,
        "body": "Some message"
        "sentDate": 00002,
    }]
}, {
    "sender_id": 5,
    "messages": [{
        "id": 11,
        "body": "Some message"
        "sentDate": 00001
    }]
}]

0
投票

一种方法可以是这样的,当您向数据添加新对象时,也添加其索引,例如,

let data = this.state.data;
let length = data.length;
this.setState({
  data:[...data, {...yourData, index:length+1}] //using ES6 spread operator
});

现在在你的 renderItem 函数中尝试类似

let {index, id, sender_id} = item //using object destruction
let lastMessage = this.state.data[index-1];
let isSame = (sender_id === lastMessage. sender_id)?true:false; //use it 

***** 一定有比这更高效的方法。


0
投票

您也可以在获取数据时仅循环一次逻辑,然后将结果提供给您的平面列表,而不是在渲染中使用逻辑:

.then((data) => {
  const messages = data.map((item, index) => {
    if (index > 0) {
      return (item.sender_id === data[index].sender_id) ? { //return object without sender id } : item;
    }
  })
  this.setState({ data: messages });
})

0
投票

使用 renderItem,我这样做了,假设你想要 true 如果相同, false 如果不同

const renderMessage = ({ item, index }) => (
    <MessageBody
      id={item.id}
      orderid={item.orderid}
      sender={item.sender}
      senderid={item.senderid}
      message={item.message}
      datetime={item.datetime}
      userimage={item.userimage}
      samesender={index == 0 ? false: chatArr[(index - 1)].senderid == item.senderid && chatArr[(index - 1)].sender == item.sender ? true: false}
    />
  )
© www.soinside.com 2019 - 2024. All rights reserved.