reactjssettimeoutflash-message

How can I send a new prop to a component after time using the setTimeout() function?


I have a component called flash that is intended to be in the DOM only for 5 seconds (it's a message informing the user that he has sent the post successfully) and I want it to start fading away after 2 seconds, so that after 5 seconds when it's removed from the DOM it already has visibility set to 0. To achieve this, in the parent component I setTimeout() and send a prop containing a boolean set to true to the flash component, where it has an if waiting for that boolean and when it gets it, it assigns a new class to that component to make it fade away. It all sounds perfect, but unfortunately it doesn't work at all... I tried updating the class within the flash component but it also doesn't work... Maybe you can come up with something? I'm sure that sending flash messages in react with pre-arranged components is a trifle in React, but I just can't think of any way of doing it!

Parent component:

        if(this.state.flashMessage){
            flash = <Flash>{this.state.flashMessage}</Flash>
            setTimeout(() => {
                //here I send the component the prop 'close' after two seconds
                flash = <Flash close>{this.state.flashMessage}</Flash>
            }, 2000);
        }

        return ( 
            <React.Fragment>
                <div className={classes.postContainer}>
                    {posts}
                    <div className={classes.Card} onClick={this.showPostAdd}>
                        <img alt="add a post" src={addPostImage} />
                    </div>
                </div> 
                {addPostActive}
                {flash}                    
            </React.Fragment>               
        );```

Here is the flash component

``` const flash = (props) => {
    let classNames = [classes.Flash];

    if(props.close){
        classNames.push(classes.TestFlash);
    }
    
    return (
        <div className={classNames.join(' ')}>
            <p>{props.children}</p>
        </div>
    );
}

Solution

  • The render only runs when updating the component, and a setTimeout won't trigger that update. However, changing a state value does trigger the update for the component.

    What you should do is print the Flash component directly on the render method and bind the close prop to a state boolean.

    <Flash close={this.state.closeFlashMessage}>{this.state.flashMessage}</Flash>
    

    And I'd put the timeout function on the componentDidMount() method.

    componentDidMount() {
        this.mounted = true;
    
        setTimeout(() => {
            //check the mounted state in case the component is disposed before the timeout.
            if(this.mounted) {
                //here I send the component the prop 'close' after two seconds
                this.setState({ closeFlashMessage: true });
            }                
        }, 2000);
    }
    
    //add this method to prevent any state management during the component's disposal
    componentWillUnmount() {
        this.mounted = false;
    }