너와 나의 프로그래밍

React.js - Button onClick으로 부모의 onChangeHandler 이벤트 발생 시키기 본문

Front-End/Next.js & React.js

React.js - Button onClick으로 부모의 onChangeHandler 이벤트 발생 시키기

Whatever App's 2023. 1. 24. 15:16

 

 

Dropdown 기능이나 SelectBox를 div와 input Element tag로 Custom하게 구현할 때 div의 목록을 클릭해서 클릭한 목록의 대한 값을 input value에 나타내주는 기능을 구현하는 도중 onClick을 했을 때 onChangeHandler로 변경하는 input value의 값을 어떻게 변경해야하는지 막막함이 다가왔다.

 

input의 value의 값을 useState Hook을 통해 변경할 때 대표적으로 2가지 방법을 사용하고 있다.

// 1. 단일적으로 선언
const [data, setData] = useState<string>("");

// 2. Object에 리스트형식으로 초기값 선언
const [data, setData] = useState<{ testData: string }>({
	testData: ""
})

변경할 state의 값들이 많지 않거나 하나만 처리하기에는 1번 방식으로 많이 사용하지만 회원가입이나 Input의 값들이 많아 한꺼번에 처리하기 위해 Object에 key: value 형식으로 초기값을 선언해서 한꺼번에 초기값을 선언하는 방식을 많이 채택하기도 한다.

 

이럴때마다 input에 onChange 속성에 onChangeHandler Function을 선언해 State의 값을 변경하는 방법을 많이 사용한다.

// 1. 단일적으로 값을 변경할 때.

const onChangeHandler = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    setData(e.target.value);
}, []);

// 2. Object 형식의 값을 변경할 때

const onChangeHandler = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    setData((prev) => ({
        ...prev,
        [e.target.name]: e.target.value,
    }));
}, []);

 

상황😥

말이 참 어려울 수 있는데 간단하게 설명한다면 부모에서 onChangeHandler Function를 통해 State를 변경하는 함수를 만들고 그 함수를 자식 컴포넌트에서 클릭이벤트로 실행시키고 싶었다.

 

하지만 부모에서 선언한 이벤트 타입 값이 버튼의 이벤트 타입 값과 다르기 때문에 이 이벤트를 도대체 어떻게 타입을 맞춰서 실행해야하는지 막막했다.

 

input의 onChange의 기본 이벤트 타입은 ChangeEvent고 Button의 기본 이벤트 타입은 MouseEvent이기 때문에 onClick 이벤트로는 event.target.value의 값을 받아 부모의 onChangeHandler에 값을 전달할 수 없는 문제가 발생했다.

Parent Component
부모의 onChangeHandler에서 사용하는 타입을 가져오려니 에러가 발생한다.

 

해결😊

해결은 MUI의 Selectbox Component와 동작하는 방법이 비슷해서 MUI에서는 타입선언을 어떻게 하고 있는지 찾아보면 해결할 수 있는 방법이 떠올라 MUI의 SelectBox Type이 선언되어 있는 MUI의 GitHub 코드를 들여다보며 해결책을 찾았다.

 

MUI에서는 자식에게 넘겨준 onChange Props에 부모에서 선언된 onChangeHandler 이벤트에서 사용하고 있는 ChangeEvnet의 target 속성의 타입과 동일하게 custom으로 추가해줬다.

 

부모에서 onChange의 대한 이벤트 값으로 name와 value값을 받아서 State 값을 변경하기 때문에 똑같이 타입을 맞춰주면 해결되는 문제였다.

 

그 후 실제 이벤트가 발생할 onClick 이벤트에 Object.defineProperty 메소드를 통해 버튼 event에 target 속성을 추가해줘서 부모의 onChange Props에 전달하여 이벤트를 실행시켰다.

 

그러나 자식 컴포넌트의 onChange의 타입을 저런식으로만 지정을 해준다면 확장성이 떨어질 뿐더러 무조건 부모의 useState값을 Object 형식으로만 선언할 수 밖에 없는 문제가 생긴다.

 

일반적으로 useState에 하나의 값을 변경하고 싶을 때도 있는데 그렇다면

 

onChange의 기본 이벤트 타입을 추가해준다.

 

기존의 Input Element의 onChange Event를 추가해주면 범용적으로 사용할 수 있다.

 

결국 Typescript의 유니온타입을 활용해서 해결할 수 있는 문제였다.

 

이 방식은 Custom한 SelectBox나 DropDown에서 클릭을 했을 때 부모에서 onChange의 대한 이벤트를 발생시키기 위해 사용하기에 정말 적절한 방식인 것 같다.

반응형