jineecode
인증번호 timer 본문
timer를 구현하기 위해서는 useRef를 써야 한다. useState만으로는 closure 안의 값까지 업데이트 해줄 수 없기 때문이다.
https://ko.reactjs.org/docs/hooks-reference.html#useref
조건:
1. 5분 이내에 인증번호 6자리 입력
const VALIDTIME = 300;
const time = useRef<number>(VALIDTIME);
// 이제 time.current 로 시간이 흘러가는 것을 추적할 수 있다.
let intervalRef: {current: NodeJS.Timeout | null} = useRef(null);
const [min, setMin] = useState(5);
const [sec, setSec] = useState(0);
2. 한 번 인증 버튼을 누르면, 20초 동안 인증 버튼을 누를 수 없음
3. 재시도 할 수 있는 횟수는 6번
const VALIDCOUNT = 6;
1. 전화번호 유효성이 통과되면, '인증' 버튼 활성화 (redux dispatch)
2. 인증 버튼 onPress, '인증' 버튼 비활성화 (redux dispatch)
2-1. timerReset callback
(처음엔 reset해주지 않아도 되지만 혹시 모르는 버그가 있을 수 있으므로 그냥 처음부터 5:00분으로 되돌리는 작업을 해주었음.)
const timerReset = () => {
clearInterval(intervalRef.current as NodeJS.Timeout);
time.current = VALIDTIME;
setMin(Math.floor(VALIDTIME / 60));
setSec(VALIDTIME % 60);
};
2-2. DB에 등록된 전화번호가 있는지 API 호출 callback
2-3. 2-2번에서 success를 타면, onPressTimer 호출 (물론 비동기로 문자 API도 같이 호출되어야 함)
2-4. onPressTimer 콜백함수가 호출되면 순차적으로 실행됩니다.
const onPressTimer = () => {
intervalRef.current = setInterval(decreaseNum, 1000);
return () => clearInterval(intervalRef.current as NodeJS.Timeout);
};
useEffect(() => {
return () => clearInterval(intervalRef.current as NodeJS.Timeout);
}, []);
useFocusEffect(
// useEffect return 으로는 cleanup이 제대로 되지 않아서, useFocusEffect 로 한 번 더 제대로 cleanup 시켜줌.
React.useCallback(() => {
return () => {
clearInterval(intervalRef.current as NodeJS.Timeout);
};
}, []),
);
const decreaseNum = () => {
time.current -= 1; // 1초씩 감소
setMin(Math.floor(time.current / 60)); //useState로 분, 시를 계속 업데이트 쳐준다
setSec(time.current % 60);
};
useEffect(() => {
if (time.current === VALIDTIME - 20 && certificationCounter > 0) {
// 20초가 지나면 다시 인증버튼 활성화
dispatch(setActiveCertification());
}
if (time.current <= 0) {
// 시간이 초과되면 clearInterval 해줌
clearInterval(intervalRef.current as NodeJS.Timeout);
}
}, [sec, certificationCounter, dispatch]);
input component의 UI
<Input
textContentType="oneTimeCode" // IOS 용
value={sms}
labelText="인증번호"
placeholder="인증번호 6자리를 입력해주세요"
onChangeText={(text) => checkCertNum(text)}
keyboardType="numeric"
maxLength={6}
innerTextIsNumber={time.current === 0} //boolean
innerText={
time.current === 0
? '시간 초과'
: `${min < 10 ? `0${min}` : min}:${sec < 10 ? `0${sec}` : sec}`
}
/>
보너스. 문자 받으면 자동으로 input에 넣어주기 (단, 안드로이드만 가능하며 권한 승인을 받아야 함)
import {useSmsUserConsent} from '@eabdullazyanov/react-native-sms-user-consent';
...
const Test = () => {
...
const retrievedCode = useSmsUserConsent();
useEffect(() => {
if (retrievedCode) {
setSms(retrievedCode);
setIsValidCertNum(true);
}
}, [retrievedCode]);
...
}
'React native' 카테고리의 다른 글
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8. (0) | 2022.07.06 |
---|---|
FlatList 의 renderItem 에 타입 지정하기 (0) | 2022.05.27 |
react-native svg 사용하기 (0) | 2022.05.25 |
react-native 라이센스 고지하기 [react-native-oss-license] (0) | 2022.05.24 |
react-native android 배포 (0) | 2022.05.24 |
Comments