Jaeilit

custom hooks 와 typescript generic 사용하여 input hooks 만들기 본문

TIL

custom hooks 와 typescript generic 사용하여 input hooks 만들기

Jaeilit 2023. 3. 18. 15:37
728x90

늘 잘 관리 된 프로젝트를 위해서 고민하고 노력하는 것을 즐기는데

인풋에 대해서 고민을 해봤다.

 

인풋은

로그인, 회원가입, 검색 등 input 을 다양한 곳에서 사용한다.

 

위에는 login page 라고 생각하고 email 과 password 2개의 input 을 만들어봤다.

 

위에서 필요한 속성은 label tag 를 제외하고

input 의 name 과 value 또 type 정도가 있을 수 있다.

 

handler fn 으로는 onChange, form 태그에 onSubmit 까지가 필수 속성일것 같다.

 

input tag 하나에 name, value, type, placeholder 는 동적으로 컨트롤 한다고 하더라도 

onChage, onSubmit 정도는 custom hooks 으로 숨길 수 있지 않을까? 생각을 했다.

 

custom hooks 로 감싸보니 hooks 에 넘기는 타입을 지정하는 것에서 난관에 부딪혔다.

그래서 이것을 해결 한 것을 이야기 해보려고 한다.

 

input custom hooks 만들어보기

 

 

1. 인풋 UI 컴포넌트화 하기

일단 input 을 컴포넌트화 해본다. Props 속성들은 전부 Input element 가 가지고 있는 속성들을 확장(extends) 해서 가져온다.

 

2. useInputHooks 커스텀 훅 제작

사실 정말 별게 없다.

리액트를 1주일만이라도 배운 사람이라도 작성할 수 있고 어디서든 많이 보는 전형적인 교과서 같은 코드라고 생각한다.

 

하지만 여기서 주목 할 점은 params 로 받는 valueObj 인데 state 의 초기 값을 valueObj로 받아와서 onChage 안에서 값을 핸들링해준다.

 

valueObj의 타입은 string key 와 string 또는 number 가 올 수 있는 value 의 객체 타입인데 여기서 내가 문제를 직면한다.

그럼 내가 hooks 에서 초기 값으로 key value 객체를 넘겼는데 그러면 사용 할때 초기 값으로 넘긴 값을 그대로 사용하게 타입가드를 해줄 수 없을까?

 

 

3. 제네릭을 사용해보자

aa

아래와 같이 email 과 password 를 login input 값으로 사용하고 싶은데

useInputHooks 는 { string : string | number } 객체를 받을거라고 타입을 가드해주지만 내가 email 과 password 를 보낼거라는 건 생각도 못하고 있으니 자동완성을 안해준다? 못해준다?

 

근래 1~2주 동안 어떤 타입의 객체를 넘겼을 때 받는 입장에서는 받은 값으로 초기 값을 자동으로 생성해줄수 없을까를 많이 고민했었는데,

 

여기서 힌트를 얻은게 제네릭과 extends 이다.

 

제네릭으로 타입에 자유(unkown)를 줄 수 있지만 반대로 extends 로 좁혀 줄 수 있다

간단히 T extends string 을 해버리면 T 는 사실 number 가 들어가도 되는 타입이였지만 T 는 string 으로 확장이 되버려서 string 속성만 가지게 된다.

 

 

4. 완성하기

 

먼저 제네릭으로 email 과 password 객체를 줘봤다.

지금은 완성형이라 에러가 표시되지 않지만 원래는 에러가 뜬다.

제네릭으로 지정한 T 값이 State의 제네릭으로 들어가서 valueObj 의 타입은 T 가 지정해준다.

T 는 string : string | number 객체 타입으로 extends 해준다.

 

5. 완성

Input_Login 으로 지정해놓은 타입이 자동완성으로 보이기 시작했다.

input 쪽에서도 제네릭을 받아줘야한다.

input 으로 name과 hooks 에서 return 한 value onChange 등을 넘겨줬다.

 

여기서 value 는 객체 타입이라는 걸 잊으면 안된다.

value 는 객체타입이니 초기에 Input Props 에 InputHTMLAttributes 에서 type error 가 발생한다.

 

이제는 value type 을 객체타입으로 overide 해줘야한다.

overide 는 typescript 의 Utils 의 Omit 으로 value 속성을 제거해주고 다시 interface 안에서 value 타입을 재정의 해주면 된다.

overide 한 value 속성도 어떤 타입의 객체가 올지 모르니 일단 제네릭으로 사용한다.

 

input 에서도 제네릭을 extends 해준다.

 

만약 이 과정을 하지 않는다면 value={value[name]} 부분에서 type error 가 발생한다.

 

value 를 value[name] 으로 받는 이유는 

name 이 email 이면 value 객체에서 key 가 email 인  value를 보여주기 위해서다.

말을 잘 못해서 그렇지, 복잡하지 않다.

 

테스트, 네 잘된다고 합니다.

728x90

'TIL' 카테고리의 다른 글

대기시간(Latency)  (0) 2023.05.19
array 중복제거 js  (0) 2023.05.19
Appollo Client 공식문서 캐시 + 캐시 맛보기(머지,리드)  (0) 2023.01.18
Next js Jest Test Setting  (0) 2023.01.08
Nextjs 13 CSS in JS 와 CSS Module 사용하기  (0) 2023.01.08