React - 유저가 입력한 폼 다루기

donggae·2023년 10월 19일
0

React

목록 보기
2/8
post-thumbnail

State를 통한 폼 컨트롤

해당 단계에서는 한 개의 폼이 아닌 두개, 세개 그 이상의 폼을 다루는 방법에 대해 알아본다.

유저가 입력할 수 있는 input, 여러 줄을 적을 수 있는 textarea, 옵션을 정할 수 있는 select에 대해서 알아보자

🙉 onChange - 입력값을 제어하자

여기서 추가로 알아야 할 것은 폼(Form)을 다루기 위해선 onChange를 사용한다는 것이다.

입력값을 제어하기 위해 onChange에 대해서 알아보자.

편의를 위해 생략되는 코드가 있음을 양해를 구한다.

const [input, setInput] = useState('');

<input value={input} onChange={(e) => {
    console.log(e);}}/>

console.log(e)에 무엇이 출력될까?

일단 해당 콘솔창을 보게되면 여러가지가 뜨는데 가장 보이는 것은 InputEvent + Object라는 것

e.target은 input을 가르킨다.

그럼이 input에서의 입력값을 알기 위해선 e.target.value 값에 접근을 해야한다.

<input value={input} onChange={(e) => {
	console.log(e.target.value);}}/>

으로 변경을 하게되면 입력을 했을 때 한 글자씩만 콘솔에 뜨는것을 볼 수 있다.

내가 원하는 것은 전체 입력값인데,,,,

내가 입력한 값을 받기 위해 setInput을 통해 얻어보자

폼에서 onChange 이벤트가 일어나면 해당 e.target.value 를 통해 input 값을 읽을 수 있지만 그 순간의 변화만 읽어주기에 setInput함수에 e.tartget.value를 넘겨주어 전체 입력 값을 얻을 수 있다.

<input value={input} onChange={(e) => {
	console.log(e.target.value);
	setInput(e.target.value);}}/>

여기서 드는 생각

만약 해당 페이지가 회원가입 페이지, 비밀번호 찾기 등 입력폼이 많으면?

const [a,setA] = useState('');
...
...
...
const [z,setZ] = useState('');

.... 또 다시 만난 무한굴레 🥵

State를 관리해보자

const [state, setState] = useState({
	input: '',
  	textarea: '',
  	select: 1,
});

return (
<div>
  <h2>입력 폼 공부하기</h2>
  <div>
    <input
      value={state.input}
      onChange={(e)=>{
      	setState({
        	input: e.target.value,
        	textarea: state.textarea,
          	select: state.select
        })
      }}
      />
  </div>
  <div>
    <textarea 
      value={state.textarea}
      onChnage={(e)=>{
      	setState({
        	input: state.input,
          	textarea: e.target.value,
          	select: state.select
        })
      }}
      />
  </div>
  <div>
        <select
          value={state.select}
          name="select"
          onChange={(e) => {
            setState({
        		input: state.input,
              	textarea: state.textarea,
              	select: e.target.value
            });
          }}
        >
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
          <option value="4">4</option>
          <option value="5">5</option>
        </select>
      </div>
</div>
)
  1. 둘다 입력 폼의 입력값의 State를 관리하는 역할이니 state로 묶어준다
  2. setState에서 input값이 변하는데 textarea값도 같이 변경되면 안된다.
  3. 그렇기에 input에 입력을 할 때엔 textarea의 값은 ''가지게 된다.

⚙️ 여기서 코드를 조금 더 수정해보자 - 1

어떤 점이 아쉬운가? -> 전 보다는 조금 관리가 쉬워진 것은 맞지만, setState에서 하지 않는것에 대한 값을 계속 불러야 한다는 점이다.

...스프레드 연산자를 사용하여 해당코드 수정하기

import { useState } from 'react';

const UserForm = () => {
  const [state, setState] = useState({
    input: '',
    textarea: '',
    select: 1,
  });

  return (
    <div className="UserForm">
      <div>
        <input
          value={state.input}
          onChange={(e) => {
            setState({
              ...state,
              input: e.target.value,
            });
            console.log(e.target.value);
          }}
        />
      </div>
      <div>
        <textarea
          value={state.textarea}
          onChange={(e) => {
            setState({
              ...state,
              textarea: e.target.value,
            });
            console.log(e.target.value);
          }}
        ></textarea>
      </div>
      <div>
        <select
          value={state.select}
          name="select"
          onChange={(e) => {
            setState({
              ...state,
              select: e.target.value,
            });
            console.log(e.target.value);
          }}
        >
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
          <option value="4">4</option>
          <option value="5">5</option>
        </select>
      </div>
    </div>
  );
};

export default UserForm;

여기서 조금 주의해야할 점은 (...)스프레드 연산자를 사용해서 기존 state를 불러오는데 이게 순서가 뒤집어 지면
바뀐 state를 기존 state로 덮게 된다. 그렇게 되면 아무리 값을 입력해도 바뀐 값에 대해서 알지 못할 것이다.

⚙️ 여기서 코드를 조금 더 수정해보자 - 2

위의 코드는 지금 태그 안에서 onChnage를 통해 state를 관리하고 있는데 이렇게 되면 코드가 너무 길어지기에 state를 관리하는 함수를 만들어서 코드를 줄여보자

state의 변화를 관리하는 handleChnageState 함수를 만든다.

const handleChnageState = (e)=>{
	setState({
    	...state,
      	"변경 되는 값":e.target.value;
    })
}

위의 코드를 보면 변경되는 값의 변화를 체크하면 되기에 해당 이벤트가 일어나는 폼의 이름만 알면 되기에 "변경 되는 값" -> e.target.name으로 변경하여 코드를 수정해보자

import { useState } from 'react';

const UserForm = () => {
  const [state, setState] = useState({
    input: '',
    textarea: '',
    select: 1,
  });

  const handleChnageState = (e) => {
    setState({
      ...state,
      [e.target.name]: e.target.value,
    });
    console.log(e.target.value);
  };

  return (
    <div className="UserForm">
      <div>
        <input name="input" value={state.input} onChange={handleChnageState} />
      </div>
      <div>
        <textarea name="textarea" value={state.textarea} onChange={handleChnageState}></textarea>
      </div>
      <div>
        <select name="select" value={state.select} onChange={handleChnageState}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
          <option value="4">4</option>
          <option value="5">5</option>
        </select>
      </div>
    </div>
  );
};

export default UserForm;

확실히 한 눈에 onChnage를 했을때 어떠한 행동을 하는지 보여서 깔끔해 진 것 같다

그럼 최종적으로 유저가 입력한 값을 얻어보자

const handleSubmit = () => {
	console.log(state)
}

<button onClick={handleSubmit}></button> 

해당 버튼을 누르게 되면 이제 다음과 같은 결과를 얻을 수 있다.

다음 장에서는 useRef 를 통하여 해당 입력값에 조건을 걸어 입력하지 않으면 포커스를 해주는 기능에 대해 알아보자

profile
아자자자

0개의 댓글