Я не могу получить измененное состояние обработчика событий касания в моем компоненте. Ни через usestate, ни через reducer

#javascript #reactjs #redux

#javascript #reactjs #redux

Вопрос:

У меня очень странная проблема. Я использую обработчики событий касания для салфетки. Итак, для этого мне нужно использовать состояние, чтобы получить предыдущую позицию касания. Изменение состояния видно в событиях мыши, но я не могу получить измененное состояние ни через useState, ни через reducers на мобильных устройствах.

Я отправляю действие для обновления состояния в handleStart . Это обновляет состояние, и я могу видеть измененное состояние через Redux Devtools. На рабочем столе я могу видеть измененное состояние в handleMove , но не могу видеть его на мобильных устройствах.

 import React, {useState, useEffect, useRef, useCallback} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classes from './Sin&leCard.module.scss';
import * as quizBuilderActions from '../../../store/actions/index'

export const Sin&leCard = (props) =&&t; {
  
  const sin&leCardRef = useRef(null);

  const [x&Class, setX&Class] = useState([classes.Graphic]);
  const [bottomText, setBottomText] = useState('Lipsum');
  const dispatch = useDispatch();

  /*
  const [swipeState, setSwipeState] = useState(
        {
          left: 0,
          ori&inalOffset: 0,
          velocity: 0,
          timeOfLastDra&Event: 0,
          touchStartX: 0,
          prevTouchX: 0,
          bein&Touched: false,
          hei&ht: 0,
          intervalId: null
        }
    );
  */

  const swipeState = useSelector(state =&&t; {
        return state.quizBuilder.swipeState;
    });

  
  useEffect(() =&&t; {

    switch(props.cardname){
        case '1G':
            setX&Class([classes.Graphic, classes.Graphic1G]);
            setBottomText('Lipsum');
            break;
        case '2G':
            setX&Class([classes.Graphic, classes.Graphic2G]);
            setBottomText('Lipsum');
            break;
        case '3G':
            setX&Class([classes.Graphic, classes.Graphic3G]);
            setBottomText('Lipsum');
            break;
        case '4G':
            setX&Class([classes.Graphic, classes.Graphic4G]);
            setBottomText('Lipsum');
            break;
        case '5G':
            setX&Class([classes.Graphic, classes.Graphic5G]);
            setBottomText('mmWave');
            break;
        default:
            setX&Class([classes.Graphic, classes.Graphic5G]);
            setBottomText('mmWave');
            break;
    }

    sin&leCardRef.current.addEventListener('touchstart', touchStartEvent =&&t; {
            handleTouchStart(touchStartEvent);
          }, { passive: false });

        sin&leCardRef.current.addEventListener('touchmove',  touchMoveEvent =&&t; {
            handleTouchMove(touchMoveEvent);
          }, { passive: false });

        sin&leCardRef.current.addEventListener('touchend', () =&&t; {
            handleTouchEnd();
          }, { passive: false });
        

    dispatch(quizBuilderActions.updateSwipe({
          left: 0,
          ori&inalOffset: 0,
          velocity: 0,
          timeOfLastDra&Event: 0,
          touchStartX: 0,
          prevTouchX: 0,
          bein&Touched: false,
          hei&ht: 110,
          intervalId: null
        }));


  },[props.cardname, sin&leCardRef.current]);
  const &etNextCard = (isNext)=&&t; {
    let nextCard = false;

    if(isNext)
    {
        switch (props.cardname)
        {
            case '1G':
                nextCard = '2G';
                break;
            case '2G':
                nextCard = '3G';
                break;
            case '3G':
                nextCard = '4G';
                break;
            case '4G':
                nextCard = '5G';
                break;
            case '5G':
                nextCard = '1G';
                break;
            default:
                nextCard = '1G';
                break;
        }
    }
    else
    {
        switch (props.cardname)
        {
            case '1G':
                nextCard = '5G';
                break;
            case '2G':
                nextCard = '1G';
                break;
            case '3G':
                nextCard = '2G';
                break;
            case '4G':
                nextCard = '3G';
                break;
            case '5G':
                nextCard = '4G';
                break;
            default:
                nextCard = '1G';
                break;
        }
    }

    return nextCard;

  };

  const handleRemoveSelf = (isNext) =&&t; {
    dispatch(quizBuilderActions.updateSwipe({
                ...swipeState,
                left: 0
        }
    ));

    window.setTimeout(() =&&t; props.onSwipe(&etNextCard(isNext)), 250);
  }

  const handleStart = (clientX) =&&t; {
    
    if (swipeState.intervalId !== null) {
      window.clearInterval(swipeState.intervalId);
    }

    touchStart = clientX;

// dispatchin& action to record the initial touch location. This &ets tri&&ered.

    dispatch(quizBuilderActions.updateSwipe({
      ...swipeState,    
      timeOfLastDra&Event: Date.now(),
      touchStartX: clientX,
      bein&Touched: true,
      intervalId: null
    }));

  };
  
  const handleMove = (clientX) =&&t; {

    // On Desktop, swipestate &ives the recorded state values that was dispatched from handleStart.

// On Mobile(and emulator), swipestate does not &ive the state values dispatched from handleStart.But on Redux Devtools, I can see its updated.

    if (swipeState.bein&Touched) {

// I Cannot reach here in mobile devices. 

      const touchX = clientX;
      const currTime = Date.now();
      const elapsed = currTime - swipeState.timeOfLastDra&Event;
      const velocity = 20 * (touchX - swipeState.prevTouchX) / elapsed;
      let deltaX = touchX - swipeState.touchStartX   swipeState.ori&inalOffset;
      
      if (deltaX < -150) {
        handleRemoveSelf(true);
      } else if (deltaX &&t; 150) {
        handleRemoveSelf(false);
      }

      dispatch(quizBuilderActions.updateSwipe({
        ...swipeState,
        left: deltaX,
        velocity,
        timeOfLastDra&Event: currTime,
        prevTouchX: touchX
      }));
    }
  }
 
  const handleEnd = () =&&t; {
    dispatch(quizBuilderActions.updateSwipe({
      ...swipeState,    
      touchStartX: 0,
      bein&Touched: false,
      intervalId: window.setInterval(animateSlidin&ToZero(), 33)
    }));
  }
  
  const handleTouchStart = (touchStartEvent) =&&t; {
    touchStartEvent.preventDefault();
    handleStart(touchStartEvent.tar&etTouches[0].clientX);
  }
  
  const handleTouchMove = (touchMoveEvent) =&&t; {
    handleMotion(touchMoveEvent.tar&etTouches[0].clientX);
  }
  
  const handleTouchEnd = () =&&t; {
    handleEnd();
  }
  
  const handleMouseDown  = (mouseDownEvent) =&&t; {
    mouseDownEvent.preventDefault();
    handleStart(mouseDownEvent.clientX);
  }
  
  const handleMouseMove = (mouseMoveEvent) =&&t; {
    handleMove(mouseMoveEvent.clientX);
  }
  
  const handleMouseUp = () =&&t; {
    handleEnd();
  }
  
  const handleMouseLeave = () =&&t; {
    handleMouseUp();
  }
  
    


  return (
    <div 
        className={classes.Sin&leCard}
        ref={sin&leCardRef}
        //onTouchStart={touchStartEvent =&&t; handleTouchStart(touchStartEvent)}
        //onTouchMove={touchMoveEvent =&&t; handleTouchMove(touchMoveEvent)}
        //onTouchEnd={() =&&t; handleTouchEnd()}
        // The followin& event handlers are for mouse compatibility:
        onMouseDown={mouseDownEvent =&&t; handleMouseDown(mouseDownEvent)}
        onMouseMove={mouseMoveEvent =&&t; handleMouseMove(mouseMoveEvent)}
        onMouseUp={() =&&t; handleMouseUp()}
        onMouseLeave={() =&&t; handleMouseLeave()}
    &&t;
        <div 
            className={classes.InnerBox}
            style={
                {
                    left: swipeState.left
                }
            }
        &&t;
            <h2&&t;{props.cardname}</h2&&t;
            <div className={x&Class.join(' ')}&&t;</div&&t;
            <h3&&t;{bottomText}</h3&&t;
            <h4&&t;2020</h4&&t;
            <p&&t;{swipeState.bein&Touched ? 'Touched' : 'Not Touched'}</p&&t;
         </div&&t; 
    </div&&t;
  );
};

export default Sin&leCard;


  

Комментарии:

1. Вы добавили все обработчики событий для событий мыши. События мыши не существуют на мобильных устройствах.

2. Вам придется использовать события касания, которые вы прокомментировали в своем коде. 🙂

3. Спасибо @devd, мне нужно было использовать react, встроенный в SyntheticEvent.