I'm trying to re-render a Button inside renderMessageImage to make its disabled property change from false to true when onPress.
I am doing it through a boolean in this.state, however I see the state value updating on the logs but the button remains visually the same and it can be pressed again and again without actually changing its disabled property.
Just setting up a simple class (eg. Chat.js) where I set the renderMessageImage to return a View with a Button which disabled property is obtained from a state value:
constructor(props) {
super(props);
this.state = {
messages: [],
isButtonDisabled: false
};
}
renderMessageImage = (props) => {
return (
<View>
<Button
title="Disable Button"
disabled={this.state.isButtonDisabled}
onPress={() => this.disableButton(props.currentMessage.id)}
/>
</View>)
}
render() {
return (
<View style={{ flex: 1 }}>
<GiftedChat
messages={this.state.messages}
user={this.user}
placeholder={"Write a message..."}
renderMessageImage={this.renderMessageImage}
/>
</View>
);
}
Then I call a simple method when onPress that button to make the isButtonDisabled state value change to true:
disableButton = async (message_id) => {
console.log("Disabling message_id: " + message_id); //This shows the msg_id correctly where the button is
this.setState(previousState => ({
isButtonDisabled: true
}));
return true;
}
Finally I am checking this.state.isButtonDisabled and it is actually changing, but the button remains enabled, it doesn't get re-rendered and thus it can be clicked again and again.
I checked that the GiftedChat.js component and messages are being updated once per button click so I guess that it should be forcing a re-render, however the button created in renderMessageImage is never re-rendering/updating to properly show its new disabled value and actually become disabled.
I'm experiencing a very similar issue where my FB messenger-esque emoji reaction popup (part of my custom message bubble) only re-renders for the top message and the most recent message. This has been a VERY common problem for a while now, so I'd love to see it fixed.
1378
1588
are the two most recent to stale out with no action.
In 1483 some claim to have gotten it to work by updating. This is definitely not working for some of us.
Just searching "re-render" on this repo gives various reformulations of this same problem dating back at least TWO years: 654
That's correct mate @charles-goode, I have followed all existing issues that have something to do with "re-rendering" and "updating" but none of the workarounds mentioned there are working for me, that is why I opened this new issue.
I guess that the required behavior could be "easily" achieved by reworking the render validation code of all the functions/methods where a state change is not currently triggering an update/render, however indeed it would be great to see it fixed once for all.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Anybody going to review this or give some useful info to us?
I'm also experiencing this, when trying to show a progress indicator for downloading my images, but the message only renders with the first progress value.
@angellobodj @charles-goode have you tried shouldUpdateMessage prop?
Please see #1483
shouldUpdateMessage={(props, nextProps) => {
return !_.isEqual(props.currentMessage,nextProps.currentMessage);
}}
Haven't tried this. My solution is to put any prop you would want to be on the message/bubble component instead as a property of the message and then update all messages each time you want to change the "prop" on one.
With shouldUpdateMessage you can put all those props in the message array itself, and a simple change will trigger a refresh. Use immer or any other inmutable lib to make changes.
I can provide an example if need.
With shouldUpdateMessage you can put all those props in the message array itself, and a simple change will trigger a refresh. Use immer or any other inmutable lib to make changes.
I can provide an example if need.
A simple example would be nice and helpful in case more people are facing this issue.
shouldUpdateMessage
how do I use this shouldUpdateMessage?! I tried and it keeps saying "is not a function" I'm calling it from renderBubble(props){ props.shouldUpdateMessage() } but it's not working
I have a similar issue where I am playing voice messages from a Bubble.
When pressing the "Play"-Button it should switch to a "Pause"-Button based on a variable in the state.
This does work, but only for the first Bubble. All other Bubbles aren't reacting to the state update. I changed my condition so that pressing any "Play"-Button should change them to "Pause"-Buttons, but again only the first Bubble is reacting to the state change.
The same can be observed with the value of the Slider Component I am using to show the progress of the voice message.
Wierd. 😐
shouldUpdateMessage
how do I use this shouldUpdateMessage?! I tried and it keeps saying "is not a function" I'm calling it from renderBubble(props){ props.shouldUpdateMessage() } but it's not working
Try updating your gifted-chat version. Mine is 0.16.3 and works ok.
With shouldUpdateMessage you can put all those props in the message array itself, and a simple change will trigger a refresh. Use immer or any other inmutable lib to make changes.
I can provide an example if need.A simple example would be nice and helpful in case more people are facing this issue.
I use two very common libs lodash and immer to make it work. This is not the only way to do.
In imports:
import _ from 'lodash';
import { produce } from "immer";
In gifted-chat prop shouldUpdateMessage:
shouldUpdateMessage={(props, nextProps) => {
return (!_.isEqual(props.currentMessage, nextProps.currentMessage));
}}
Then make inmutable changes in message array, example using immer. Assuming the messagearray is in this.state.msgarr and a boolean "play" msg property that does something (from memory, untested):
//make a change
togglePlay(msgidx) {
this.setState({ msgarr: produce(this.state.msgarr, draft) => {
draft[msgidx].play = !draft[msgidx].play;
});
}
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Damn stale bot putting the pressure on.
So as I see it right now I have to do some parkour because the chat bubbles do not properly react to my state changes.
Right?
I think the take away from this thread should just be: don't try to pass state to items of the internal flatlist by making your renderItems (a.k.a renderBubble prop) a closure; instead make the change on the item itself. FlatList uses shallow comparison for items, so as long as the data you want to alter on an item would be detected as such, it will rerender.
For example, OP wants to pass disabled to a particular message, he should add a property of the message data object indicating that the message should or should not be "disabled."
His issue was that he was passing state to his custom render indirectly as a closure so RNGC and specifically the internal FlatList could not always determine that the list should rerender. Additionally it would probably rerender the whole list with that implementation which is why the react native team favored the other method.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Most helpful comment
I'm experiencing a very similar issue where my FB messenger-esque emoji reaction popup (part of my custom message bubble) only re-renders for the top message and the most recent message. This has been a VERY common problem for a while now, so I'd love to see it fixed.
1378
1588
are the two most recent to stale out with no action.
In 1483 some claim to have gotten it to work by updating. This is definitely not working for some of us.
Just searching "re-render" on this repo gives various reformulations of this same problem dating back at least TWO years: 654