功能 setTimeout 在其他点击后不起作用

Function setTimeout not working after other clicks

我创建了一个简单的 toast,它在第一次运行时有效,但是当我第二次单击它时它不起作用,我不知道为什么它不起作用。我试图查看其他答案,但没有找到 大家有什么建议吗

让我们看看代码

我的 toast 组件

export class Toast extends PureComponent<any> {

  state = {
        timePassed: false
    };

    componentDidMount() {
       setTimeout( () => {
            this.setTimePassed();
        },2000);
       clearTimeout()
    }

    setTimePassed() {
        this.setState({timePassed: true});
    }

    render() {
        const { color, title, subtitle } = this.props
        if (this.state.timePassed){
            return '';
        }else{
            return (
                <div className="toast">
                    <p>{title}</p>
                    <div>{subtitle}</div>
                </div>
            );
        }
    }

用法如下

export class Product extends PureComponent<any> {

    state = {
        like: true,
        icon: <Icon.HeartEmpt/>,
        toast: ''
    }


    handleClick() {
        this.setState({like: !this.state.like})
        if (this.state.like) {
            this.setState({toast:  <Toast color='green'  title='Produto adicionado' subtitle='Produto adicionado aos favoritos'/>})

        } else {
            this.setState({toast:  <Toast color='red' title='Produto removido' subtitle='Produto removido dos favoritos'/>})
        }
    }

    render() {
        return (
            <>
                <div className='product'>
                    {this.state.toast}                  
                </div>
            </>
        )
    }

}

您应该在 Parent 组件而不是 Toast 本身处理 Toast 消失。所以你在 Product 触发了 setTimeout。不要像 @c0mit 说的那样在 store 存储 JSX 组件。

我也会删除 toast 的状态。因为它依赖于 like,我会将它的内容存储在一个对象上并通过 like 值访问(这将是 addedremoved)。

您还需要确保在卸载组件时清除 setTimeout。在 componentDidUpdate 你触发了你的 setTimeout,但是你需要检查它是否没有触发 setTimeout 并且 disPlayToast 是 true.

export class Toast extends PureComponent<any> {
 
    render() {
        const { color, title, subtitle } = this.props

        return (
            <div className="toast">
                <p>{title}</p>
                <div>{subtitle}</div>
            </div>
        );
    }
}

const toastProps = {
  liked: { 
    color:'green', 
    title:'Produto adicionado',
    subtitle:'Produto adicionado aos favoritos'
  },
  removed: {
    color:'red',
    title: 'Produto removido',
    subtitle:'Produto removido dos favoritos'
    }
  }

class Product extends PureComponent<any, any> {

    state = {
        like: 'removed',
        displayToast: false
    }

    // timeHandler to store setTimeout
    timerHandle = 0

    componentDidUpdate() {
      // to trigger setTimeout validate that Toast is on display
      // and timerHandle 
      if(this.state.displayToast && !this.timerHandle){ 
        this.timerHandle = setTimeout(() => {
          this.setState({ displayToast: false });
          // clear timerHandle     
          this.timerHandle = 0;  
        },2000);
      }
    }

      componentWillUnmount = () => {             
    // clearTimeout if it's running               
    if (this.timerHandle) {                  
        clearTimeout(this.timerHandle);      
        this.timerHandle = 0;                
    }                                        
  };                                         


    handleClick = () => {
        this.setState(( { like } ) => ({
          like: like === 'liked' ? 'removed' : 'liked', 
          displayToast: true })
        )
    }

    render() {
        const {like, displayToast} = this.state
        return (
          <div>
            <button onClick={this.handleClick}>filp</button>
            <div className='product'>
                {displayToast && <Toast {...toastProps[like]} />}                  
            </div>
          </div>
        )
    }
}

https://stackblitz.com/edit/so-toast-timeout?file=index.tsx