클릭시 debounce 하는 방법에 대해서 궁금한게 있습니다

다른페이지는 StackNavigator를 사용해서 다른 페이지를 보여줍니다.
버튼1을 빠르게 여러번 클릭시 여러창이 뜨는 것을 확인 한 후 버튼 1을 클릭시

  onPress={debounce(() => {
          this.props.onPress();
        }, 400)}

이렇게 각 버튼에 debounce를 걸어서 여러번 클릭해도 한번만 작동하도록 했습니다. 하.지.만…
빠르게 버튼1을 클릭 후 버튼 2를 클릭 후 다시 버튼 1을 클릭하면 페이지가 중첩이 되는 현상이 다시 발생하였습니다.
어떻게 해결하는 것이 좋을지 조언을 얻고자 질문을 올립니다…

아래는 debounce 구현부분입니다.

export function debounce(func, wait, immediate) {
  
  var timeout;
  return function() {
    var context = this,
      args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

(써놓으신 debounce는 작동이 되지 않습니다. 그 이유는 렌더되는 컴포넌트의 onPress attr에 람다식으로 써놓으셔서 해당 컴포넌트가 리렌더될때마다 람다함수도 싹 리셋되기때문에 var timeout이 남아있지 않기 때문입니다.) <- 죄송합니다 저의 추측;; 이었습니다. 어떤 식으로 함수를 쓰셨는지, 또 그 함수가 선언된 부분의 스코프 부분을 보지 못했네요. 하지만 func부분의 함수가 자꾸 재선언되어서 문제가 될 수 있어 보입니다.

함수를 컴포넌트의 attr로 올려서 this.timeout으로 쓰시던지 아니면 컴포넌트 바깥에 두고 전역변수로 쓰셔도 되지만 제가 추천하는건 lodash/debounce를 쓰시는 겁니다

제가 react-navigation에 대해 잘 몰라서 대충 만들어 봤는데요;; 이런 느낌으로 하시면 될 것 같습니다 https://gist.github.com/marsinearth/bbc7dfa17c78784669cd08f9337bd8f2

2 Likes

써놓으신 식에서 debounce(this.props.onPress, 400) 이라고 하시면 될 것 같습니다;;

1 Like

와…자세하게 알려주셔서 너무너무 감사합니다. 오전중으로 시도해보겠습니다!!! :slight_smile:

1 Like

계속 시도해봤는데 마찬가지 인것같습니다…
버튼 하나에 대해서는 제어가 가능하지만
연속적으로 버튼1 =>버튼2=>버튼1을 누르면 버튼1에 해당되는 페이지가 2번 중첩됩니다…

Debounce를 throttle로 바꿔보시면 어떨까요? 정해진 시간 내에 요청된 여러번의 시도를 한번 빼고 다 무시하는건데