일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- react-hook-form
- satisfiles
- frontend
- java
- typescript
- hook
- go
- golang
- storybook
- test
- JavaSpring
- css
- ReactHooks
- javascript
- springboot
- Spring
- RTK
- component
- Gin
- backend
- 웹애플리케이션서버
- tanstackquery
- 티스토리챌린지
- JPA
- Chakra
- 오블완
- Redux
- designpatterns
- React
- Today
- Total
bkdragon's log
react-daum-postcode, antd, react-hook-form 조합하기 본문
제목에 나온 3가지 라이브러리를 함께 사용하면서 얻은 경험을 공유해보려고 한다.
각각의 라이브러리의 설치법이나 사용법에 대해서는 깊게 설명하지 않을 것을 미리 알린다.
Modal창 안에 react-daum-postcode 넣기
import { Modal } from 'antd'; // 모달 컴포넌트 불러오기
import DaumPostcodeEmbed from 'react-daum-postcode'; // 주소 입력 컴포넌트 불러오기
...
const [isModalOpen, setIsModalOpen] = useState(false); // 모달을 열지 판단할 상태값
...
return (
...
{isModalOpen &&
<Modal open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<DaumPostcodeEmbed onComplete={handleComplete}/>
</Modal>
}
...
)
이때 컴포넌트의 네이밍을 예쁘게 바꾸고 싶으면 아래와 같이 할 수 있다.
export const AddressModal = styled(Modal)``; // styled-components 상속 문법
export const AddressSearchInput = styled(DaumPostcode)``;
react-daum-postcode의 onComplete
react-daum-postcode의 onComplete 속성은 주소선택을 완료했을 때 실행할 함수를 받는다. 함수의 타입은 내부를 보면 다음과 같다.
oncomplete?: (address: Address) => void;
당연히 Address 타입도 제공이 되기 때문에 이용해서 함수를 커스텀 할 수 있다. onComplete에 넣을 handleComplete를 다음과 같이 만들 수 있다. 주소와 코드를 받을 상태도 만들었다.
const [address, setAddress] = useState<string>(''); // 주소를 넣을 상태
const [zoneCode, setZoneCode] = useState<string>(''); // 우편번호를 넣을 상태
...
const handleComplete = (data : Address) => {
setZoneCode(data.zonecode)
setAddress(data.address)
setIsModalOpen(false)
console.log(address, zoneCode); // e.g. '서울 성동구 왕십리로2길 20 (성수동1가)'
};
이 상태를 input 창 value에 넣어주었다.
return (
...
<S.Zipcode placeholder="07250" readOnly value={zoneCode || ''} />
<S.Address readOnly value={address || ''} />
...
)
Input창에 react-hook-form register 연결
return (
...
<S.Zipcode placeholder="07250" readOnly value={zoneCode || ''} {...register('zipcode')} />
<S.Address readOnly value={address || ''} {...register('address')} />
...
)
이렇게 연결을 했는데, input창에 입력이 안되는 현상이 발생했다. register 내부 동작과 value에 직접 값을 넣는 부분에 있어서 호환이 안되는 것 같다. 그래서 register 내부를 살펴보았다.
// register에 마우스를 올려보니 UseFormRegister 타입이였다. 바로 가보자.
export type UseFormRegister<TFieldValues extends FieldValues> = <TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(name: TFieldName, options?: RegisterOptions<TFieldValues, TFieldName>) => UseFormRegisterReturn<TFieldName>;
// UseFormRegisterReturn 반환하는 함수이다. 그렇다면 UserFormRegisterReturn은?
export type UseFormRegisterReturn<TFieldName extends InternalFieldName = InternalFieldName> = {
onChange: ChangeHandler;
onBlur: ChangeHandler;
ref: RefCallBack;
name: TFieldName;
min?: string | number;
max?: string | number;
maxLength?: number;
minLength?: number;
pattern?: string;
required?: boolean;
disabled?: boolean;
};
UserFormRegisterReturn에서 onChange를 찾았다! 이것을 활용하기로 했다. 컴포넌트 내부에서 전개 연산자로 사용하던 register를 변수로 따로 빼서 사용하는 방법을 썼다.
const {onChange : onAddressChange, ...addressRegistration} = register('address')
const {onChange : onZoneCodeChange, ...zoneCodeRegistration } = register('zipcode')
...
return (
...
<S.Zipcode placeholder="07250" readOnly value={zoneCode || ''} onChange={(e) => onZoneCodeChange({type : e.type, target : e.currentTarget.value})} {...zoneCodeRegistration}/>
<S.Address readOnly value={address || ''} onChange={(e) => onAddressChange({type : e.type , target : e.currentTarget.value})} {...addressRegistration}/>
...
)
input 태그 value에 상태를 넣어두고 onChange target에 e.currentTarget.value로 접근했다.
발생하던 오류가 사라졌다! 내부 코드를 보며 잘 호환되지 않던 라이브러리를 연결했다.
추가적인 문제 발견
다시 확인해보니 주소데이터가 넘어가지 않는 문제가 발생했다. 로컬 상태 값을 react-hook-form에서 사용하기위해 useForm의 리턴타입을 살펴보던 중 setValue라는 것을 찾았다. name과 value를 받아 registerd 된 값을 업데이트 해주는 메서드이다.
setFormValue('address', fullAddress)
setFormValue('zipcode', data.zonecode)
위 코드를 추가했더니 주소데이터가 잘 넘어가게 되었다.
'concept' 카테고리의 다른 글
Flux 패턴 (0) | 2023.07.17 |
---|---|
[TEST] MSW와 통합 테스트 (0) | 2023.07.12 |
[TEST] 프론트의 단위 테스트와 BDD (0) | 2023.07.09 |
[Test] Jest, React-testing-library (0) | 2023.07.07 |
[JavaScript] Call Stack, Callback Queue (0) | 2023.06.24 |