I am using ReactJS. In my app, if an error occurs, I need to display a message to the user for a programable amount of time.
I would normally implement a stateless UI component based only on the props, but knowing I need a timer, I instead create a React Component called Message to manage the timer and state.
export class Message extends React.Component {...}
Within this Message component, I convert the props to state within the constructor, and update the state within componentWillReceiveProps if nextProps are different from the present state. Also within the component, I start the timer if there is a timeout specified. At timeout, the components state of the message is nulled, which results in the component no longer displaying the message.
When the App receives an error, it creates the message:
<Message message="You have big problems." timeout=5000 />
and all works as expected, the error message is displayed for 5 seconds.
But I have been unable to get it working properly to simultaneously manage these two use cases:
Case 1: After the first error occurs and has been displayed, a second error can occur that is identical to the first, requiring the error to be displayed again.
Case 2: The App can re-render based on other state changes, in which case we are not to re-display the error.
To manage case 1, I set the state of message within the Message component to null after the timer expires. Since this message state variable is used as the condition to display the message, the message disappears. When a second error occurs with a message equivalent to the first error, the new message prop is now different from the nulled message state within the Message component, causing a new message to be displayed for a new timeout.
This works great except now when case 2 occurs, it causing a re-render of the components, including a re-render of the last error message that occurred, inappropriately resulting in the user seeing another message displayed.
I know that if I lifted up the timer out of the Message component and placed it in the app/parent, I could cause the Message component to be rendered after the timeout, and this would make it work, but it seems so wrong to not be able to manage the timeout lifecycle in the Message component itself.
Is there any solution to this? Or did I indeed discover the scenario that cannot be easily managed with ReactJS?
Thank you.
One way to control it is to have a couple of extra props on your Message
:
onTimeout() {
this.setState({ open: false });
}
render() {
const { open } = this.state;
<Message open={open} onTimeout={this.onTimeout} message="..." timeout={5000} />
}
The open
prop would control whether the message is rendered at all. If open
is set to false
, any timers should be cancelled. The onTimeout
function should be called once the timeout fires, from here, you can control the visibility state.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments