#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.