개발 중 기존 쿠폰 등록하는 부분의 UI 수정과 함께 플로우도 수정되며 새로 작성한 코드가 있어 기록해두고자한다
기존엔 쿠폰함에 가면 바로 쿠폰번호를 등록했다면
수정 후 플로우
: 버튼 선택 -> 쿠폰등록 dialog 오픈 -> 번호 작성 및 확인 -> 등록, 에러처리 등 작업을 하게되었다
hook의 watch도 써보고 onChange도 써봤지만 useRef가 가장 간결하게 만들 수 있었다.
사실 처음엔 useState에 focus의 true, false값을 제어하는 형태로 진행하다가 포커스 이동 시 재랜더로 인한 불필요한 동작들이 추가되어 useRef로 구현했다.. 확실히 더 개발하다보면 state를 최대한 적게쓰면서 작성하는 tip이 필요하다 더 연구해봐야지!
const inputRefs = [useRef<HTMLInputElement>(), useRef<HTMLInputElement>(), useRef<HTMLInputElement>(), useRef<HTMLInputElement>()];
// 작성 후 다음 textfield로 포커스 이동시키기
const handleInputChange = (name: string) => {
const nextFieldName = `num${Number(name.charAt(3)) + 1}`;
if (getValues(name).length >= 4) {
inputRefs.map((e: any, i: number) => {
if (nextFieldName === `num${i + 1}` && inputRefs[i].current) {
inputRefs[i].current.focus();
}
});
}
};
-> return쪽 코드
<Stack direction={'row'} sx={{ flex: 1, pt: '2px', p: pxToRem(20), gap: 1 }}>
{inputRefs.map((e: any, i: number) => {
return (
<CTextField
key={`cpn-${i}`}
name={`num${i + 1}`}
label=""
variant="outlined"
className={'InquiryTextArea'} // style이 같아서 사용
help={false}
maxLength={4}
sx={{ maxHeight: 40}}
inputRef={inputRefs[`${i}`]}
resizeType={'none'}
onChangeCallback={() => handleInputChange('num' + `${i + 1}`)}
/>
);
})}
</Stack>
**dialog 오픈 시 첫번째 CTextField만 focus상태로 오픈되게 만들기 위해 아래 코드를 추가하여 덧붙인다
그냥 추가하면 아마 focus가 안될 것이다ㅜ
dialog의 렌더가 끝난 후 적용해야하기 때문이다.
복잡한 코드는 아니지만 랜더 시점에 따라 다른 부분들이 있어서 시점을 고려하여 구현할 필요가 있다
// Dialog 렌더링이 완료 후 적용 가능
useEffect(() => {
if (openRegister) {
setTimeout(() => {
inputRefs[0].current && inputRefs[0].current.focus();
}, 0);
}
}, [openRegister]);
아주 유용한 정보네요!