본문 바로가기
프로그래밍 언어/HTML, CSS

[Trouble Shooting] <input> 태그에서 undefined가 제출되는 경우

by whale in milktea 2023. 4. 11.

React 프로젝트를 진행하다가 아래와 같은 오류가 발생했다.

(본 사례의 경우 이미 해결한 내용을 다시 점검하고 해결하느라 예시 코드를 활용했다.)

import "./styles.css";

export default function App() {
  const handleSubmit = (e) => {
    console.log(e.target.value); // 일단 여기서 undefined 출력
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input type="text" />
      </form>
    </div>
  );
}

사실, 이 문제에 대한 다음 스텝은 어렵지 않게 찾을 수 있었다.

기존에 본인이 코드를 짜면서 input에서 event를 다루는 연습을 종종 했기에 사전에 작성했었던 코드들을 살펴봄으로서 찾을 수 있었다.

 

<form> 태그는 내부에서 제출되는 각 요소가 제출한 최종 이벤트들을 모아서 하나의 객체로 제출하는 역할!

그렇기 때문에 input 태그에도 별도의 이벤트 핸들러가 필요했다.

평소 해왔던 대로 새로운 상태를 선언하고, <input type="text" onchange={(e) => setValue(e.target.value)}를 넣어서 코드를 다시 테스트했다.

 

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [value, setValue] = useState("");

  const handleSubmit = (e) => {
    console.log(e.target.value);
  };

  const handleInputEvent = () => {
    console.log(value); // undefined...
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          onChange={handleInputEvent((e) => setValue(e.target.value))}
        />
      </form>
    </div>
  );
}

이 부분에서 많이 헤맸다...

분명 동일한 프로젝트의 파일 안에서는 문제없이 작동되는 코드가 작동되지 않았다.

 

해결 뒤의 코드는 다음과 같다.

import "./styles.css";

export default function App() {

const handleSubmit = (e) => {
    console.log(e.target.value);
  };

  const handleInputEvent = (e) => {
    console.log(e.target.value); // 정상출력!
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          onChange={handleInputEvent}
        />
      </form>
    </div>
  );
}

근데, 내가 작성한 대부분의 경우에는 undefined가 출력된 위의 코드와 같이 작성했다. 본인은 "이벤트 핸들링"에 관한 부분에서 뭔가 놓치고 있는 것 같아서 문제를 해결하면서 차근차근 접근하고자 했다.

 

이벤트 핸들링, 뒷단에서 이뤄지는 일

이벤트 핸들링은 사용자가 타자를 칠 때, 마우스를 클릭할 때 특정한 작업을 수행하도록 명령하는 작업을 말한다.

React 코드에서는 대부분 이벤트 핸들러 함수를 통해 이뤄진다.

이 때 해당 이벤트가 발생했을 때 실행되도록 함수를 등록하는 것을 통상 이벤트 핸들러에 전달한다고 표현한다.

 

뒷단에서는 이벤트가 발생했을 때, 이벤트 객체를 생성하고 함수에 첫번째 인자로 전달한다.

import "./styles.css";

export default function App() {
  const handleSubmit = (e) => {
    console.log(e.target.value);
  };

  const handleInputEvent = (e) => {
    console.log(e);
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input type="text" onChange={handleInputEvent} />
      </form>
    </div>
  );
}

// 이 때, handleSubmit과 handleEventSubmit에 전달되는 이벤트 객체는 다음과 같다.

여기서 자주 쓰이는 e.target.value는 HTML 요소에서 일어난 여러 정보 중 가장 핵심 정보인 "값"만을 의미한다.

 

그렇다면, 첫번째 코드에서는 왜? 이벤트 전달이 제대로 이뤄지지 않는가?

첫번째 코드에서 이벤트 핸들러에 해당하는 함수를 바꾸면 다음과 같다.

// handleInputEvent((e) => setValue(e.target.value))

function handleInputEvent(event) {
  setValue(event.target.value);
}

// ...

<input
  type="text"
  onChange={handleInputEvent}
/>

이 때, 이벤트가 발생하면 이벤트를 처리하는 순서는 다음과 같다.

1. 사용자가 <input> 요소에 텍스트를 입력하거나 변경할 때마다 onChange 이벤트가 발생한다.
2. onChange 속성에 정의된 handleInputEvent((e) => setValue(e.target.value)) 함수가 호출되고 실행된다.
3. 여기서 문제가 발생한다. handleInputEvent 함수는 인수 없이 정의되었지만, 이 코드에서는 (e) => setValue(e.target.value) 함수를 인수로 전달하려고 시도하고 있다. 그러나 이렇게 작성하면 handleInputEvent 함수가 먼저 호출되고, 그 결과가 onChange에 전달된다.
4. handleInputEvent 함수는 반환 값이 없으므로 undefined를 반환한다.
5. 따라서 onChange 속성은 undefined 값을 받게 된다.
6. onChange 속성은 함수가 아닌 값(undefined)을 받았으므로 이벤트 처리를 할 수 없고, 결과적으로 handleInputEvent 함수가 이벤트 객체를 전달받지 못하고, 입력 값 변경 시 이벤트 처리가 제대로 이루어지지 않게 된다.

 

즉, 인수없이 정의된 함수임을 이벤트 핸들러 함수를 등록할 때에는 이해가 부족하여 확인할 수 없음을 인지하지 못하고 "동작함"에 의미를 두고 그대로 복붙했기 때문에 발생한 해프닝이었다..

 

이벤트 핸들링을 할 때에는 다음의 내용을 신경써야 한다.

 

1. 이벤트 핸들러는 이벤트가 발생한다면 반드시 이벤트 객체를 생성한다.

2. 그리고 이를 자동으로 전달하는 것이 아닌 이벤트 핸들러 함수에 첫번째 인자로 정의된 부분에 전달된다.

3. 내가 사용했던`handler((e)=>(e.target.value)`식은 아무런 인자를 받지 않는 함수이다. 동일한 맥락에서 (e) => handler(e.target.value)는 인자를 일단 익명함수에서 첫번째 인자를 받은 뒤에 핸들러 함수에 value만을 전달하는 함수이다.

4. 즉, 호출 시점에서 어떤 함수에 전달하고 어디에 사용할 것인지에 따라 상태에 담아둘지, 상태 관리 툴로 관리할지, 바로 변수에 담아 활용할지, 아니면 함수의 인자로 넘겨 새로 mapping 등의 작업을 수행할 것인지 파악할 수 있어야 한다.

'프로그래밍 언어 > HTML, CSS' 카테고리의 다른 글

검색 엔진 최적화(SEO)  (0) 2023.03.01
Sementic Tag(웹 표준)  (0) 2023.02.28