Search code examples
reactjsreact-nativereact-native-gifted-chat

how to set ID for every bubble message and then update using its ID


Easy way to understand what is my question play the following video and see what is my problem. https://vimeo.com/315390850

if you dont have a good inernet connection then read the following sentences.

I am going to update bubble messages but i dont know how to update specific message by Id. Example: in html there is and Id for every tag within a list and if we have to update then we select it by id and then update it. So how to make a concept like that for react-native-gifted-chat bubble messages?

I tried to use refs with setNativeProps function but did not work.

render(){
 return (
   <GiftedChat
         extraData={this.state}
         messages={this.state.messages}
          onSend={messages => this.onSend(messages)}
          user={{
              _id: this.state.userId,
           }}
           renderBubble={this.renderBubble}
           renderInputToolbar={this.renderInputToolbar.bind(this)}
      />
 );
}

renderBubble = props => {
        if (props.currentMessage.audio) {
            return (
                <View style={[{ width: 150, height: 70, backgroundColor: 'lightgray' }, props.position === 'left' ? { left: -41 } : {}]}>
                    <EIcon
                        name="google-play"
                        size={30}
                        color={this.state.playAudio ? "red" : "blue"}
                        style={{
                            left: 90,
                            position: "relative",
                            shadowColor: "#000",
                            shadowOffset: { width: 0, height: 0 },
                            shadowOpacity: 0.5,
                            backgroundColor: "transparent"
                        }}
                        onPress={() => {
                            this.setState({
                                playAudio: true
                            });
                            const sound = new Sound(props.currentMessage.audio, "", error => {

                                if (error) {
                                    console.log("failed to load the sound", error);
                                }

                                const duration = sound.getDuration();
                                const progressPhase = 1 / duration;

                                if (duration !== 0) {
                                    this._interval = setInterval(() => {

                                        this.setState({
                                            progress: this.state.progress += progressPhase
                                        });

                                        if (this.state.progress >= 1) {
                                            clearInterval(this._interval);
                                            this.setState({
                                                progress: 0.0,
                                                playAudio: false
                                            });
                                        }

                                    }, 1000);
                                }

                                sound.play(success => {
                                    console.log(success, "success play");
                                    if (!success) {
                                        Alert.alert("There was an error playing this audio");
                                    }
                                });

                            });
                        }}
                    />


                    <Progress.Circle progress={this.state.progress} showsText size={35} />

                </View>
            );
        } else {
            return (
                <Bubble
                    {...props}
                    textStyle={{
                        right: {
                            color: '#fff',
                        },
                        left: {
                            color: '#fff',
                        },
                    }}
                    wrapperStyle={{
                        left: {
                            backgroundColor: "orange",
                            left: -41
                        },
                        right: {
                            backgroundColor: 'green'
                        }
                    }}
                />
            );
        }
    }

Here I have a chatbox when I send multiple audio message for example 3 aduio message: audio message .1, audio message .2, audio message .3 aduio message .1 has came first time. aduio message .3 has came last time.

every audio message has a play icon and a progressbar. When I click on play Icon, then I update the progressbar. here I used interval for one click on play icon, the progressbar gets update multiple time until gets complete.

My Problem is: when i click the play icon of audio message .1 just the last audio message .3 gets updated. I want: if I click on audio message .1 the progressbar of audio message .1 should be update. same for audio message .2 and audio message .3.


Solution

  • I solved my problem by conditional rendering Also I changed following class and I added this line: next.audio == current.audio ||

    export default class Message extends React.Component {
    
      shouldComponentUpdate(nextProps) {
        const next = nextProps.currentMessage;
        const current = this.props.currentMessage;
        const { nextMessage } = this.props;
        const nextPropsMessage = nextProps.nextMessage;
        return (
          next.send !== current.send ||
          next.received !== current.received ||
          next.pending !== current.pending ||
          next.createdAt !== current.createdAt ||
          next.text !== current.text ||
          next.image !== current.image ||
          next.video !== current.video ||
          next.audio == current.audio ||  // this line added by me
          nextMessage !== nextPropsMessage
        );
      }
    
     //..............
    
    }
    

    I add this condition and please please let me know about performance. this tree line, I added to my code:

    this.myPro = <Progress.Circle progress={this.state.progress} showsText size={35} />; this.setState({currentPlayedMessage: props.currentMessage._id }); { props.currentMessage._id === this.state.currentPlayedMessage ? this.myPro : null }

    All code:

    if (props.currentMessage.audio) {
    
                this.myPro = <Progress.Circle progress={this.state.progress} showsText size={35} />; // this line added
    
                return (
                    <View style={[{ width: 150, height: 70, backgroundColor: 'lightgray' }, props.position === 'left' ? { left: -41 } : {}]}>
                        <EIcon
                            name="google-play"
                            size={30}
                            color={this.state.playAudio ? "green" : "blue"}
                            style={{
                                left: 90,
                                position: "relative",
                                shadowColor: "#000",
                                shadowOffset: { width: 0, height: 0 },
                                shadowOpacity: 0.5,
                                backgroundColor: "transparent"
                            }}
                            onPress={() => {
    
                                this.setState({
                                    playAudio: true,
                                    currentPlayedMessage: props.currentMessage._id // this line added
                                });
    
                                const sound = new Sound(props.currentMessage.audio, "", error => {
    
                                    if (error) {
                                       return;
                                    }
    
                                    const duration = sound.getDuration();
                                    const progressPhase = 1 / duration;
    
                                    if (duration !== 0) {
                                        this._interval = setInterval(() => {
    
                                            this.setState({
                                                progress: this.state.progress += progressPhase
                                            });
    
                                            if (this.state.progress >= 1) {
                                                clearInterval(this._interval);
                                                this.setState({
                                                    progress: 0.0,
                                                    playAudio: false
                                                });
                                            }
    
                                        }, 1000);
                                    }
    
                                    sound.play(success => {
                                        console.log(success, "success play");
                                        if (!success) {
                                            Alert.alert("There was an error playing this audio");
                                        }
                                    });
    
                                });
                            }}
                        />
    
    
                        { props.currentMessage._id === this.state.currentPlayedMessage ? this.myPro : null } // this line added
    
                    </View>
                );
            }