첫번쨰로 Swipe를 이용해서 아래 동영상과 같이 퀴즈에 대한 문제를 풀수 있도록 움직여주는 부분을 만들어보자!
(이런 부분들은 공식문서를 참고하면은 참 쉽게 할 수있다는데 아직은 완벽하게 이해한게 아니다보니 공식문서도 어렵다ㅠㅠ)
반복하여 이해하는게 좋을 것 같다!!
1. 사전준비
패키지 설치하기
yarn add react-tinder-card
Quiz.js에서 사용을 해야하므로 설치한 패키지를 임포트해오는걸 잊지말자!
import TinderCard from "react-tinder-card";
세부적인 내용은 공식문서 참고하자.
https://www.npmjs.com/package/react-tinder-card
2. 스와이프 적용 전 퀴즈문제 코드 수정
- 우리가 작성한 퀴즈 문제는 총 4가지이므로, 문제들을 순서대로 보여주려면 스와이프가 되어야하는 영역에 map 돌려줘야한다.
<QuizContainer>
......
{props.list.map((l, idx) => {
// 리스트 하나를 l 이라고하며, 리스트 하나에 대한 idx 를 가져온다.
return (
<DragItem key={idx}>
<div>
<img src={img}
</div>
</DragItem>
);
})}
</QuizContainer>
이렇게하면은 정상적으로 문제가 뜨는걸 볼 수 있다. 하지만, 맵을 돌려서 보여주다보니 여러개 중복되서 보여지게 된다.
이럴때 내가 풀고있는 문제에 해당하는 부분만 보여주도록 추가 작업을 해줘야한다.
state를 활용해서 문제 하나하나 넘어갈때마다 저장하도록 해보자.
const Quiz = (props) => {
const [num, setNum] = React.useState(0);
}
....
<QuizContainer>
<p>
<span>{num+1}번 문제</span>
//몇번문제인지도 state에 저장한 넘버로 가져올 수 있다. index는 1번부터 시작이니까 +1 해주면 끝!
</p>
{props.list.map((l, idx) => {
if(num === idx) {
return(<Question key={idx}>{l,question}</Question>);
}
})}
{props.list.map((l, idx) => {
// 리스트 하나를 l 이라고하며, 리스트 하나에 대한 idx 를 가져온다.
if(num === idx) {
return (
<DragItem key={idx}>
<div>
<img src={img}
</div>
</DragItem>
);
}
3. 스와이프 적용하기(Tinder-Card)
자세한 내용은 위에 공식문서를 참고해보자. 공식문서가 어렵더라도 시간될때마다 자주 읽어보자.
const onSwipe = (direction) => {
console.log("You swiped: " + direction);
}
return (
<QuizContainer>
...
<DragItem>
<TinderCard onSwipe={onSwipe}>
<img src={img}
</TinderCard>
</Dragitem
//기존 div를 스와이프 사용을 위해 TinderCard로 변경
이렇게 코드를 변경해주면 이미지가 정상적으로 움직이는걸 볼 수 있다!
또한 개발자 콘솔에서 콘솔로그 찍은것처럼 "You swiped + direction" 을 볼수있다. right , left 등등
이제 setNum 값을 통해 다음문제로 넘어갈 수 있도록 코드를 작성해보자.
const onSwipe = (direction) => {
setNum(num+1);
console.log("You swiped: " + direction);
}
return (
<QuizContainer>
...
스와이프하면은 정상적으로 다음문제로 넘어가는걸 볼 수 있다!
4. EventListner 적용하기
touch event 를 통해서 이벤트가 동작하도록 작업해보자.
https://developer.mozilla.org/ko/docs/Web/API/Touch_events
스와이프 Quiz.js 전체가 아닌 일부분에 대해서만 적용할거기때문에 새로운 파일을 만든다.
SwipeItem.js
* 기본 형태
import React from "react";
import styled from "styled-components";
import img from "./scc_img01.png";
const SwipeItem = React.memo(({ onSwipe }) => {
//memo는 memoization라고 불리우며, 간략하게 렌더가 여러번되는걸 방어해준다.
<DragItem>
<img src={img}
</DragItem>
});
...
SwipeItem.defaultProps = {
onSwipe: (direction) => {},
};
// props를 받아서 쓸때 props가 없을때 에러가 나는걸 방지하기위해 props는 기본적으로 어떤값을 가지고있다고 알려주는 코드
export default SwipeItem;
이제 Quiz.js에서 가져다가 사용할 수 있도록 임포트해주자.
import SwipeItem from "./SwipeItem";
또, DragItem 부분은 SwipeItem에 불러와서 작성을 해주었기때문에 삭제해주고 아래와같이 작성해주면된다.
{quiz.map((l, idx) => {
if (idx === num) {
return <SwipeItem key={idx} onSwipe={onSwipe}/>;
}
})}
이제는 터치이벤트를 만들어주면된다.
addEventListner 를 사용하기위해서 ref를 먼저 잡아주자.
* ref 사용예시
- 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
- 애니메이션을 직접적으로 실행시킬 때.
- 서드 파티 DOM 라이브러리를 React와 같이 사용할 때.
const swipe_div = React.useRef(null);
//함수형컴포넌트에서 ref잡는방법
...
return (
<DragItem ref={swipe_div}>
<img src={img} />
</DragItem>
);
});
useEffect를 통해서 이벤트리스너를 처음 한번만 등록을 해주면된다.
React.useEffect(() => {
};, []);
// useEffect() 는 컴포넌트가 렌더링 될때마다 특정 작업을 실행할 수 있도록 해주는 훅이다!!
// useEffect() 안에 동작한 이벤트를 작성해준다.
const reset = () => {
}
const touchStart = (e) => {
}
const touchEnd = (e) => {
}
const touchMove = (e) => {
}
const touchCancel = (e) => {
}
// 필요한 이벤트 기본형태는 만들었으니, 이벤트 리스너를 등록하면된다.
swipe_div.current.addEventListener("touchstart", touchStart);
swipe_div.current.addEventListener("touchend", touchEnd);
swipe_div.current.addEventListener("touchmove", touchMove);
swipe_div.current.addEventListener("touchcancel", touchCancel);
항상 이벤트리스너를 등록해줬다면 해제도 해줘야한다.
return () => {
// 만약 이벤트 걸었던 엘리먼트가 없으면 해제하지 않는다!
if (!swipe_div.current) {
return;
}
swipe_div.current.removeEventListener("touchstart", touchStart);
swipe_div.current.removeEventListener("touchend", touchEnd);
swipe_div.current.removeEventListener("touchmove", touchMove);
swipe_div.current.removeEventListener("touchcancel", touchCancel);
};
기본형태가 준비가 되었다면 전체 완성한 코드에 대한 설명은 별도로 정리해보자!
처음부터 만드는건 어렵기때문에 하나하나보면서 어떤 원리로 동작하는지 이해하는데 집중하자.
'내마음대로만들어보자 > React' 카테고리의 다른 글
[Router/Redux] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.09 |
---|---|
[EventListener 코드설명] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.09 |
[조건부렌더링/state 데이터 관리] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.08 |
[퀴즈,점수화면 뷰만들기] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.05 |
[시작화면] 우정테스트 사이트 만들기(Feat.리액트) (1) | 2021.08.04 |