Почему debounce не вызывает мою функцию?

Я работаю над чем-то с React и MOBX.

Я создал Компонент ImageCarousel, где я показываю изображение, на которое нажали. У меня есть предыдущая и следующая кнопки (которые сами являются компонентом), для перемещения между изображениями.

Я пытался обернуть эти действия (предыдущий и следующий) lodash debounce, но что-то не получается на пути.

Мой текущий магазин имеет следующие действия:

  • prevCarousel
  • nextCarousel
  • debounceAction

debounceActionэто просто функция высшего порядка, которая получает 2 параметра (fn, wait) и вызываетlodash debounceс этими параметрами.

Мой компонент CarouselButton проходит через все те действия, о которых я говорил выше. внутри компонента, который я запускаю сonClickсобытие для вызоваdebounceAction(fn, wait)с фактическим действием (предыдущий илиследующий).

Я не уверен, как правильно обернуть мои действия с debounce.

Я призываюdebounceAction(HOF, который оборачивает ответ) во втором фрагменте кода (в компоненте CarouselButton).

ты видишь мою ошибку здесь?

galleryStore.jsx- текущий магазин:

class GalleryStore {

    // Observables    
    @observable images = [
        // ....images
    ];

    @observable carouselleButtons= {
        next: "fa fa-chevron-right",
        back: "fa fa-chevron-left"
    }
    @observable selectedImageIndex = null;
    @observable hideCarousel = true;
    @observable onTransition = false;

  // Actions
    selectImage = (index) =>{
        this.selectedImageIndex = index;
    }

    toggleCarousel = () =>{
        this.hideCarousel = !this.hideCarousel;
    }

    carouselNext = () => {
        if(this.selectedImageIndex == this.images.length - 1) {
            return;
        }

        this.onTransition = true;
        setTimeout(() => {
            this.selectedImageIndex = this.selectedImageIndex + 1;
            this.onTransition = false;
        },500)
    }

    carouselPrev = () => {
        if(this.selectedImageIndex == 0) {
            console.log('start of the collection');          
            return;
        } 

        this.onTransition = true; 
        setTimeout(() => {
            this.selectedImageIndex = this.selectedImageIndex - 1;
            this.onTransition = false;        
        }, 500)       
    }

    debounceAction = (fn, wait) => {
        //lodash's debounce
        return debounce(fn, wait);
    }

Компонент carouselButton-здесь я вызываю дебат:

// React's
import React from 'react';

// Styles
import CarouselButtonStyle from './carouselButtonStyle';

// CarouselButton Component
export default class CarouselButton extends React.Component {
    debounce = (e) =>{
        const { debounceAction } = this.props;

        // ----->    HERE I CALL DEBOUNCE !   <---------
        e.stopPropagation();
        debounceAction(this.buttonHandler, 400);
    }

    buttonHandler = (e) => {
        const {limit, index, action, debounceAction} = this.props;

        if(index == limit)  return;
        else action();
    }

    render(){
        const {limit, index, icon, action, debounceAction} = this.props;

        return(
            <CarouselButtonStyle 
                onClick={(e) => {this.debounce(e)}} 
                className={ index == limit ? 'end-of-collection' : '' } >

                <i className={icon} aria-hidden="true" />
            </CarouselButtonStyle>
        );
    }
}

imageCarousel.jsx-родительский компонент carouselButton:

// React's
import React from 'react';

// Mobx-react's
import { observer, inject } from 'mobx-react';

// Styles
import ImageCarouselStyle from './imageCarouselStyle';

// Components
import ImgContainer from './imgContainer/imgContainer';
import CarouselButton from './carouselButton/carouselButton';

// ImageCarousel Component
@inject('galleryStore')
@observer
export default class ImageCarousel extends React.Component {
    closeCarousel = () => {
        this.props.galleryStore.toggleCarousel();
    }

    onKeyDown = (e) => {
        const { keyCode } = e;

        if(keyCode ===27) this.onEscHandler();
        else if (keyCode == 37) this.onLeftArrow();
        else if (keyCode == 39) this.onRightArrow();
        else return;
    }

    onLeftArrow = () => { this.props.galleryStore.carouselPrev()  }

    onRightArrow = () => { this.props.galleryStore.carouselNext() }

    onEscHandler = () => { this.closeCarousel() }

    componentDidMount(){
        document.addEventListener('keydown', this.onKeyDown, false);
    }

    render(){
        return(
            <ImageCarouselStyle 
                hidden={this.props.galleryStore.hideCarousel}
                onClick={this.closeCarousel} >

                <CarouselButton action={'prev'} 
                    icon={this.props.galleryStore.carouselleButtons.back} 
                    action={this.props.galleryStore.carouselPrev}
                    limit={0}
                    index={this.props.galleryStore.selectedImageIndex} 
                    debounceAction={this.props.galleryStore.debounceAction} />

                <ImgContainer 
                    images={this.props.galleryStore.images} 
                    imgIndex={this.props.galleryStore.selectedImageIndex} 
                    onTransition={this.props.galleryStore.onTransition}/>

                <CarouselButton action={'next'} 
                    icon={this.props.galleryStore.carouselleButtons.next} 
                    action={this.props.galleryStore.carouselNext} 
                    limit={this.props.galleryStore.amountOfImages}
                    index={this.props.galleryStore.selectedImageIndex} 
                    debounceAction={this.props.galleryStore.debounceAction} /> 

            </ImageCarouselStyle>
        );
    }
}

1 ответ

Решение

Проблема в том, что вы должны вернуться debounceAction от CarouselButton "s debounce метод.

debounce = (e) =>{
    const { debounceAction } = this.props;

    // ----->    HERE I CALL DEBOUNCE !   <---------
    e.stopPropagation();
    debounceAction(this.buttonHandler, 400);
// -^^^ must return here
}

Однако я бы предложил пойти дальше, чтобы избежать путаницы в будущем. Просто вызвать Лодаша debounce когда вам это нужно, вместо того, чтобы переписывать его несколько раз в коде, что приводит к сомнительным именам методов.

Вот самый простой пример того, как вы можете обернуть обработчик клика:

class Button extends React.Component {
  handleClick = _.debounce((e) => {
    alert('debounced click reaction')
  }, 1000)

  render() {
    return <button onClick={this.handleClick}>CLICK ME</button>
  }
}

ReactDOM.render(
  <Button />,
  document.getElementById('app')
);
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Другие вопросы по тегам