Developer/React

React, 이벤트 처리와 hook/ useState/useState를 활용한 객체 관리

단님 2024. 6. 11. 19:39
728x90
React의 이벤트 처리

1. 이벤트 리스너의 카멜 표기 (낙타 표기법)

- onClick , onChange ...

2. 콜백 함수 처럼 함수의 객체 참조 (주소값을 기술).

3.기본 이벤트 제거할것.

- a 링크 와 form 태그의 submit

- 기본이벤트 제거 ( return false 대신 e.preventDefault() 명시적으로 호출해야함 )

 

  •  HTML 의 클릭이벤트와 JSX의 클릭 이벤트 차이
  • HTML의 클릭 이벤트 : onclick=clickTest();
  • JSX의 클릭 이벤트 : onClick={clickTest}
 
 
콜백함수(banana)의 사용과 객체 참조형 함수(apple).
 
 
 
    const clickTest = (e) =>{
        alert(`안녕하세요 = ${e.target.name}`);
    }
<button name='apple' onClick={clickTest}>
   Apple 을 클릭하세요
</button>

<button name='banana' onClick={(e)=> clickTest(e)}>
   Banana 를 클릭하세요
</button>

 



React 의 HOOK 이란 ?

이전에 클래스형 컴포넌트와 함수형 컴포넌트가 존재했다고 했다.

클래스란 여러개의 함수를 가진 구조를 지님으로 ,

클래스형 컴포넌트는 클래스의 문법을 사용하나 , 클래스 컴포넌트 또한 내부적으로 함수형으로 존재하기 때문에,

추후에 클래스형 컴포넌트가 아닌 함수형 컴포넌트를 지향하게 되었다.

함수형 컴포넌트를 사용함에 있어서 클래스형 컴포넌트의 좋은 기능들을 활용하기위해 HOOK이 생겨났으며,

HOOK은 클래스형 컴포넌트에서 가지고 있던 유용한 기능들을 제공하는 역할을 지닌다.

특징적으로 구분하기 위해 use~ 라고 명명하였다.

 

그중에 우리는 useState를 먼저 알아보도록 하자.

 

State란 무엇인가 ?

 

값을 저장하거나 변경할수 있는 객체로 이벤트와 함께 주로 사용된다.

 

1. import { useState } from "react";

react 에서 useState를 import 한다.

 

1. useState 생성자 함수를 통해 State를 생성한다.

const [state변수, setState함수] = useState("초기값");

useState를 생성하면 , 현재 상태값 , 변경하기위한 함수 를 담은 배열이 반환된다.

배열을 구조분해 할당을 받아 사용하는 구조라고 볼 수 있다.

setState 함수는 관례상 state에 해당하는 변수명에 set을 붙여 사용하여 가독성을 높인다.

 

const stateAr = useState(0),
        count = stateAr[0], 
        setCount = stateAr[1];
        
const [count, setCount] = useState(0);

-useState의 구조분해 할당된 과정.

 

상태값이 바뀌어 리액트 돔과 html 돔구조가 달라진것이 확인된다면 , 

랜더링되어 적용된다.

 

 

리랜더링이란 ?

상태값(=비동기값)이 변화 됬을때 리랜더링이 발생된다.

동기값이 변한다고 다시 리랜더링이 되지 않는다.

비동기가 변화한다고 리랜더링 되는것이 아님의 주의

버튼이벤트가 발생한다고 해도 값이 변하지 않으면 랜더링 되지 않기에 용어에 주의하자.

 

랜더링이 된다는 말은 값이 변한 해당 함수내의 전체실행이 일어난다.

그로 인해 , 내부의 값을이 리셋될 수 있음을 의미한다.

 

리액트에서 랜더링은 랜더링의 목적성을 가지고 , 무분별하게 랜더링이 발생되지않게,

필요한 부분의 랜더링만 발생되도록 한다면 최적화에 신경 쓸 수 있겠다.

 

랜더링을 확인해보고싶으면 , 개발자 도구를 이용하여 컴포넌트를 활성화 시키는 방법도 있고,

상태값이 변하는 함수안에 콘솔출력 하나 해놓는다면 , 랜더링 될때마다 함수가 재실행되어 ,

콘솔출력이 되는것으로 랜더링을 확인 할 수 있다.

   //  컴포넌트 업데이트 메세지를 확인.
    console.log('랜더링');

 

 

case 1. input 의 value 값의 변화를 인지하여 span 에 출력. 

            const [text ,setText] = useState('');
        <h2>2.test</h2>
        <input type="text" value={text}
        onChange={(e)=>{setText(e.target.value)}} /><span>{text}</span>

- onchange 이벤트를 통해 이벤트의 주체인 input(e.target)의 value 값을 인지하여, 그 값을 span에 출력.

 

 

case 2. input 의 date 타입과 , select 의 선택된 값을 콘솔에 출력하기.

    const [date , setDate] = useState('');
    const [option, setOption] = useState('');
    const dateChange = (e)=>{
        setDate(e.target.value);
        console.log(e.target.value);
    }
    const jobChange = (e)=>{
        setOption(e.target.value);
        console.log(e.target.value);
    }
        <input type="date" value={date} onChange={dateChange}/>
        <select name="" value={option} onChange={jobChange}>
            <option value="Java개발자">Java개발자</option>
            <option value="React개발자">React개발자</option>
            <option value="음악가">음악가</option>
            <option value="교육자">교육자</option>
            <option value="바리스타">바리스타</option>
        </select>

- input 의 date 타입의 value 값을 dateChange 라는 함수를 통해 값이 변할 때를 감지하여 , 

그 값을 date라는 변수에 저장한다.

 

-select 의 value 값도 jobChange라는 함수를 통해 값이 변할 때를 감지하여 , 

그 값을 option 에 넣어 저장한다.

 

각 저장된 date 의 변수와 option의 변수가 저장되면서 콘솔에 찍는 작업을 하고 있다.

 

 

HTML 의 select 의 value 는 초기값으로 , option 태그의 첫 요소이거나,

option 태그중 selected 라는 속성을 추가하여 첫 value 값을 정할 수 있었다

 

리액트를 통하여 useState에 초기값을 지정함으로서 , HTML의 selected 효과를 얻을 수 있다.

 const [option, setOption] = useState('음악가');


useState의 객체형 관리

 

useState의 객체형 관리가 왜 필요할까 ?

이를 알아보기 위해 개별적 관리의 케이스부터 다시 보겠다.

 

// ** State 로 여러개의 사용자 입력 관리하기
import { useState } from "react";


export default function Body (){
    const [name, setName] = useState('');
    const [gender, setGender] = useState('');
    const [birth , setBirth] = useState('');
    const [info, setInfo] = useState('');

    const nameChange = (e)=>{
        setName(e.target.value);
        console.log(e.target.value);
    }
    const genderChange = (e)=>{
        setGender(e.target.value);
        console.log(e.target.value);
    }
    const birthChange = (e)=>{
        setBirth(e.target.value);
        console.log(e.target.value);
    }
    const infoChange = (e)=>{
        setInfo(e.target.value);
        console.log(e.target.value);
    }

    console.log('랜더링 확인');


    // input tag의 개별적 값 관리

    return(
        <>
        <h2> 1. input 태그의 개별적 관리 </h2>
        <input type="text" 
            value={name} onChange={nameChange} placeholder="이름"
            style={{margin : '5px'}}/>
        <select name="" value={gender} onChange={genderChange} style={{margin : '5px'}}>
            <option hidden>성별</option>
            <option >여성</option>
            <option >남성</option>
        </select>
        <div>
        <input type="date" value={birth} onChange={birthChange} style={{margin : '5px'}}/>
        </div>
        <div>
            <textarea 
                value={info} 
                onChange={infoChange} 
                cols="50" rows="10" 
                style={{resize : "none", border : ' 3px solid hotpink' , margin : '5px', 
                    borderRadius : '10px' , boxShadow : '5px 5px 5px silver'}}></textarea>
        </div>
        </>
    )
}

 

변경된 값을 저장하기 위해서 onChange의 이벤트를 발생하고 , 

그 상태값들을 담는 4개의 useState를 준비했다.

그렇다면 4개의 state 변수를 따로 추후에 값이 변경될때마다 객체로 묶어줄것인가 ?

 

이를 해결하기 위해 애초에 useState를 객체로 준비해보자.

    const [member, setMember] = useState({
        name :'',
        gender :'',
        birth : '',
        info : '',
    });

useState로 생성한 객체의 속성값들을 태그의 name값 으로 받고 ,

useState로 생성한 객체의 value 값을 이전에 onChange를 감지한 태그의 value 값을  넣어주자.

        <h2> 1. input 태그의 개별적 관리 </h2>
        <input type="text" 
            name='named' onChange={memberChange} placeholder="이름"
            style={{margin : '5px'}}/>
        <select name='gender' onChange={memberChange} style={{margin : '5px'}}>
            <option hidden>성별</option>
            <option >여성</option>
            <option >남성</option>
        </select>
        <div>
        <input type="date" name='birth' onChange={memberChange} style={{margin : '5px'}}/>
        </div>
        <div>
            <textarea 
                name='info'
                onChange={memberChange} 
                cols="50" rows="10" 
                style={{resize : "none", border : ' 3px solid hotpink' , margin : '5px', 
                    borderRadius : '10px' , boxShadow : '5px 5px 5px silver'}}></textarea>
        </div>

위와 똑같은 코드인데 name 값으로 객체의 속성값을 주고,

change 이벤트를 함께 사용하고 있다.

 

change 이벤트를 보겠다.

    const memberChange = (e)=>{
        console.log(`*이벤트가 일어나는 대상은 ? ${e.target.name}`);
        console.log(`*이벤트 대상의 값은 ? ${e.target.value}`);
        setMember({
            ...member,
            [e.target.name]:e.target.value
        });

이벤트 주체가 되는 객체의 name 값 : 이벤트 주체가 되는 객체의 value 값을 가져와

( e.target.name속성을 key로 e.target.value를 value로 저장 )

펼침 연산자를 통해 추가해주었다.

펼침 연산자를 보기위해서는 펼침연산자 다시보기

객체괄호표기법 : 속성명을 괄호('[]')로 감싸서 표현한다.

 

위에 코드에서는 따로 value속성을 지정해주지 않아도 value 값을 가져오는데 문제가 없지만, 

useState를 활용하여 초기값을 관리하기가 편하기 위해서는

각 value에도 속성을 지정해주는것이 내생각엔 맞는것 같다..

value={member.named}
value={member.gender}
value={member.birth}
value={member.info}

각 태그에 추가해 주도록 하자.

 

코드 결과를 확인해 본다면