Reputation:
I have a created a MessageList component for displaying return messages from the server, I want these messages to only exist in the state for around 5 seconds or so, I have it all working as I want for adding and displaying, but I cant think for the life of me how to timeout the removal of a specific item from its parent array.. a Vanilla JS answer will do for timeout removal of self from array.
var MainApp = React.createClass({
AddComment: function() {
//do some stuff
this.showMessage({
alerttype: "success",
title: "Success!",
message: "Comment saved to the database."})
}
},
showMessage: function(message) {
//how to I push this message onto messages for 5 seconds?
},
getInitialState: function() {
return {messages: []};
},
render: function () {
return (
<div className="mainApp">
<CommentForm messages={this.state.messages} />
</div>
);
}
});
Upvotes: 1
Views: 1803
Reputation: 4670
All you need to do is wrap the removal in a setTimeout. Something like the below:
showMessage: function(message) {
this.setState({
messages: this.state.messages.concat([message])
});
setTimeout(() => this.setState({
messages: this.state.messages.filter(m => m !== message)
}), 5000);
},
Upvotes: 0
Reputation: 3114
Let's try to abstract this from your view logic. We can make a data type that's responsible for storing timestamped messages. We can also add some helper functions to remove old items and to retrieve the current list of items. Then all you need to do is occasionally purge any old items:
function ExpiringMessages(expirationTime) {
this.messages = [];
}
ExpiringMessages.prototype.add = function (data) {
this.messages.push({ timestamp: Date.now(), data });
}
ExpiringMessages.prototype.removeOlderThan = function (delta) {
this.messages = this.messages.filter(m => (Date.now() - m.time) - delta > 0);
}
ExpiringMessages.prototype.current = function () {
return this.messages.map(m => m.data);
}
This basically just stores a list of timestamped data that allows you to purge any items whenever you want. Within your component, you would set an interval (maybe every second or so) that would remove items that are older than 5 seconds. Each time you do this, you would reset the current list of messages to be messages.current()
.
Upvotes: 1
Reputation: 14101
One way to do this is use timestamps on messages and add a separate cleanup method on a 5 second timeout:
showMessage()
, update your state with the new message, and add a timestamp to the new message.componentDidUpdate()
lifecycle method, which calls a cleanMessages()
method, and fires a 5 second timeout to call the cleanMessages()
method` again.cleanMessages()
method, check if any of the messages in the list is > 5 seconds old (by comparing current time to timestamp in each message), remove found old messages, and only if there are messages removed, do a setState()
with the updated messages list.By the way, it looks like the line }.bind(this);
in your code breaks the code and should be removed.
Upvotes: 0