Web/React+React Native

Input 상태 관리 +useRef

1. 단일 Input 필드 상태 관리하기

=> input에 입력하는 값이 하단에 나타나게 하고, 초기화버튼을 누르면 input 값이 비워지도록 구현을 해본다.

 

 

   -InputSample.js

 

=> 이번에도 useState를 사용하고, input의 onChange 이벤트를 사용하여 이벤트에 등록할 함수에서는 이벤트 객체 e를 파라미터로 받아와서 사용한다. 이 객체의 e.target은 이벤트가 발생한 Input DOM을 가리키게 된다.

 e.target.value로 접근하면 현재 input에 입력한 값이 무엇인지 알 수 있다.

 

import React,{useState} from 'react';

function InputSample(){
   const [text,setText]=useState('');
   //초기값 설정
   
   const onChange=(e) =>{
    setText(e.target.value);
    }
    
    const onReset=(e)=>{
    setText('');
    }
    
    return(
    <div>
     <input onChange={onChange} value={text}/>
     <button onClick={onReset}>초기화</button>
     <div>
     <b>값:{text}</b>
     </div>
    </div>
    );
}

export default InputSample;

 

input의 상태를 관리할 때에는 input태그의 value값도 설정해주는 것이 중요하다. 그렇게 해야 상태가 바뀌었을 때

input의 내용이 업데이트된다. 

 

 

2. 여러개의 input 상태 관리하기

 => input이 여러개 일때는 어떻게 관리해야 하는가?

 

:input의 개수가 여러개가 됐을 때는 단순히 useState를 여러번 사용하고, onChange도 여러개 만들어서 구현할 수 있다.

=> 가장 좋은 방법은 input에 name을 설정하고, 이벤트가 발생했을 때 이 값을 참조하는 것이다. 

 

import React,{useState} from 'react';

function InputSample(){
    const[inputs,setInputs]=useState({
        name:'',
        nickname:''
    });

    const{name,nickname}=inputs;

    const onChange=(e)=>{
         const{value,name}=e.target;//e.target에서 name,value를 추출한다.

         setInputs({
             ...inputs,//기존의 input 객체를 복사한 후
             [name]:value//name 키를 가진 값을 value로 설정한다.
         });
    };

    const onReset=(e)=>{
       setInputs({
           name:'',
           nickname:'',
       })
    };

    return(
        <div>
            <input name="name" onChange={onChange} placeholder="이름"/>
            <input name="nickname" onChange={onChange} placeholder="닉네임"/>
            <button onClick={onReset}>초기화</button>
            <>
            <b>이름(닉네임):</b>{name},{nickname}
            </>
        </div>
    )
}

export default InputSample;

 

# 리액트 상태에서 객체를 수정해야 할 때에는?

 

inputs[name]=value;

=> 이런식으로 직접 수정해서는 안된다. 그 대신에 새로운 객체를 만들어서 새로운 객체에 변화를 주고, 이를 상태로 사용해야 한다.

 

setInputs({
  ...inputs,
  [name]:value
});

=> 여기서 사용한 ...문법은 spread문법으로, 객체의 내용을 모두 펼쳐서 기존 객체를 복사해준다.

=> 이를 불변성을 지킨다고 하는데,  이 불변성을 지켜줘야만 리액트 컴포넌트에서 상태가 업데이트됐음을 감지할 수 있고, 이에 따라 필요한 리렌더링이 진행되다. 위와 같이 기존 상태를 직접 수정하게 되면, 값을 바꿔도 리렌더링이 되지 않는다. ( 기존의 값과 다른지를 비교하여 리렌더링을 진행하는 것 같다..?)

 

3. useRef로 특정 DOM 선택하기

 JavaScript를 사용할 때에는, 우리가 특정 DOM을 선택해야 하는 상황에 getElementById, querySelector와 같은 DOM selector를 이용해 DOM을 선택한다.

 

=> react를 사용하는 프로젝트에서도 가끔 DOM을 선택해야 하는 상황이 있다.

   EX) 특정 엘리먼트의 크기를 가져오던가, 스크롤바 위치를 가져오던가, 포커스를 설정해준다던가 하는 다양한 상황이 존재한다.

  

=> 그럴 땐, 리액트에서 ref라는 것을 사용한다.

 : 함수형 컴포넌트에서 ref를 사용할 때에는 useRef라는 Hook 함수를 사용한다.

 

 

- InputSample.js

import React,{useState,useRef} from 'react';

function InputSample(){
    const[inputs,setInputs]=useState({
       name:'',
       nickname:'' 
    });

    const nameInput=useRef();
    //useRef()를 사용하여 Ref객체를 만들고, 이 객체를 우리가 선택하고 싶은 DOM에 ref값으로 설정해줘야 한다.


    const[name,nickname]=inputs;

    const onChange=e=>{
        const{value,name}=e.targe;
        setInputs({
            ...inputs,
            [name]:value
        });
    };

    const onReset=()=>{
        setInputs({
            name:'',
            nickname:''
        });
        nameInput.current.focus();
        //그렇게 하면, Ref객체의 .current값은 우리가 원하는 DOM을 가르키게 된다.
        //onReset함수에서 input에 포커스하는 focus() DOM API를 호출해주었다.

    }

    return(
        <div>
            <input name="name" onChange={onChange} placeholder="이름"/>
            <input name="nickname" onChange={onChange} placeholder="닉네임"/>
            <button onClick={onReset}>초기화</button>
            <>
            <b>이름(닉네임):</b>{name},{nickname}
            </>
        </div>
    )


}