국비교육과정 정리/React

[React] State, Event

백설마을꿀단지 2023. 1. 16.

State

State란 컴포넌트 내부에서 변경될 수 있는 데이터를 관리해야할 때 사용되는 객체이다. 데이터가 변경이 되는 경우 변화를 감지하여 컴포넌트를 다시 리랜더링시킨다. 클래스/함수형 컴포넌트에 따라 사용방법이 다르며, 함수형 컴포넌트에선 hook을 이용해 좀 더 간편하게 사용할 수 있다.

 

cf) props는 컴포넌트 내부에서 값을 변경할 수 없지만 state는 컴포넌트 내부에서 변경이 가능하다.

 

state 특징

- state는 타입을 구분하지 않는다.(str, number, obj ....)

- state는 직접 수정해서는 안되며, 값을 변경하고자 한다면 반드시 set 함수를 이용해서 변경해야 한다.

 

🤔 set함수를 이용해서 변경해야하는 이유

state는 immutable(불변성)을 유지해야하기 때문이다.
컴포넌트는 현재의 this.state와 setState를 비교해서 업데이트가 필요한 경우에만 render 함수를 호출하는데, state를 직접 수정하게 되면 리액트가 render 함수를 호출하지 않아 상태 변경이 일어나도 렌더링이 일어나지 않을 수 있다. 

그렇기 때문에 상태 변경을 추적하고 변경에 따라 구성요소를 다시 렌더링하기 위해서 직접 변경이 아닌 setState를 사용해야 한다.

 

- 일반적으로 state는 이벤트와 같이 사용된다. (컴포넌트 내에서 그냥 set함수만 사용 시 리랜더링이 무한히 반복되어 에러가 발생하게 된다. 그래서 이벤트와 같이 특정 상황에 한 번만 랜더링이 되도록 한다.)

- state는 여러 개 사용이 가능하다.

 

UseState

useState는 가장 기본적인 Hook으로 함수형 컴포넌트에서 변경가능한 상태를 지니고 있을 수 있도록 한다.

오직 함수형 컴포넌트에서만 사용할 수 있으며 state라는 요소(내부에서 변화되는 값)를 다루기 쉽게 제공되는 내장함수이다.

data에는 지정한 초기값이 담기며, setter에는 data 값을 변경할 수 있는 set함수가 담긴다.

useState 사용방법

1) 배열로 받아서 배열 값 꺼내기

   const data = useState('초기값');
   let a = data[0]; //data : 초기값
   let b = data[1]; //값을 변경하는 함수

 2) 구조분해해서 받아오기

   let [data, setData] = useState('초기값');

 

함수형 컴포넌트 state 사용 예시

import { useState } from "react"



const StateComponent = () => {

   let [data, setData] = useState('초기값');
   let func = () => setData('변경')
   let enter = () => setData('입장')

   let [color, setColor] = useState('black');

   return (
      <>
         <h3 style={{color:color}}>state값: {data}</h3>
         <button onClick={func}>값 변경하기</button>
         <button onClick={enter}>입장</button>
         <button onClick={()=>setData('퇴장')}>퇴장</button>
         <hr/>
         <button onClick={()=> setColor('red')}>Red</button>
         <button onClick={()=> setColor('blue')}>Blue</button>
         <button onClick={()=> setColor('black')}>Black</button>
      </>
   )
}

export default StateComponent

 

클래스 컴포넌트에서 state 사용법

- state는 생성자 안에서 초기화를 해야한다. 접근은 this.state를 이용한다.

- state의 값을 설정할 때는 반드시 객체모형을 사용해야 한다.

 

import { Component } from "react";
class MyComponent3 extends Component {
   constructor(props) { //props를 매개변수로 받아야 한다.
      super(props); // 클래스형 컴포넌트는 반드시 super를 사용
      this.state = { // 객체 모형으로 state 값 부여
         a : 1,
         b : props.name
      }
   }
   render () {
      let {name} = this.props;
      return (
         <>
            <div>props 값: {name}</div>
            
            //this.state.key값 으로 부여한 데이터를 꺼낼 수 있다.
            <div>state 값: 첫 번째 = {this.state.a}, 두 번재 = {this.state.b}</div>
         </>
      )
   }
}
export default MyComponent3;

 

Event 

- 컴포넌트 내에서 이벤트의 이름은 반드시 카멜 표기법으로 표현한다. (onclick -> onClick)

- 이벤트를 전달할 때는 {함수}형태로 사용한다.

 

인풋값 핸들링 실습

- 인풋의 값이 변화되는 이벤트 onChange 연결

- 이벤트 안 첫 번째 매개변수에서 event 객체 활용하기 (e.target.속성값)

- setter를 이용해서 state 변경하기

 

import { useState } from "react";
const EventComponent = () => {   
   let [data1, setData1] = useState('');
   let [data2, setData2] = useState('');

   let hadlename = (e) => {
      setData1(e.target.value)
   }

   const handleClick = () => {
      alert(`${data1}님의 주제는 ${data2}입니다.`);
      setData1('');
      setData2('');
   }

   return(
      <>
         <h3>리액트 이벤트핸들링 (인풋데이터)</h3>
		 //함수 정의해서 사용하기
         <input type="text" name="name" onChange={(hadlename)} value = {data1}/>
         <div>체인지 결과: {data1}</div>
         
		 //익명함수 사용
         <input type="text" name="topic" onChange={(e) => setData2(e.target.value)} onKeyUp={handlePress} value = {data2}/>
         <div>체인지 결과: {data2}</div>

         <button type="button" onClick={handleClick} value = {data1}>버튼</button>
      </>
   )
}

export default EventComponent;

 

Event 응용

state가 여러 개 있을 경우 각 state마다 useState를 사용해야하기 때문에 코드가 복잡해질  수 있다.

값을 데이터가 아닌 객체로 주었을 경우 하나의 setSate로 여러 개의 state를 관리할 수 있다.

const [data, setData] = useState({name: '기본이름', topic: '기본제목'});

 

⛔ 값을 객체로 주었을 경우 객체 안 데이터를 변경하고자 할 때는 set 함수를 바로 사용해서는 안된다.

set 함수를 사용해서 객체를 변경하였을 경우 state는 변경된 객체의 주소를 참조하게 된다. 그렇기 때문에 state가 값이 변경되었다는 것을 인지하지 못하고 리랜더링을 수행하지 않는다.

그렇기 때문에 state가 원본의 객체를 참조하도록 하여 값이 변화되었다는 것을 인지할 수 있도록 해야한다.

 

💡 객체를 참조하고 있는 state 변경 방법

- set 함수로 객체의 내용을 바로 변경하는 것이 아니라 임시의 객체를 만들어서 기존의 객체를 복사를 한다.

- 복사된 객체의 데이터를 변경한다.

- 변경 완료된 복사객체를 set함수를 이용해서 대입한다. (원본과 비교하였을 때 값이 변경되었음을 인지할 수 있으므로 리랜더링이 정상적으로 작동된다.)

 

예시

import { useState } from "react";
const EventComponent2 = () => {
	//state에 객체 대입
   const [data, setData] = useState({name: '', topic: ''});

   const handleChange = (e) => {
   
   	  // 데이터 복사 후 원하는 키값 변경하기
      let copy = {...data, [e.target.name] : e.target.value};
      
      //변경된 copy 데이터 state 대입
      setData(copy); 
   }
   const handleClick = () => {
      alert(`${data.name}님 할 일: ${data.topic}`);
      setData({name:'', topic:''});
   }

   return (
      <>
      <h3>리액트 이벤트 핸들링(객체)</h3>
      <input type="text" name = "name" value = {data.name} onChange={handleChange}/>
      <div>결과: {data.name}</div>
      <input type="text" name = "topic" value = {data.topic}onChange={handleChange}/>
      <div>결과: {data.topic}</div>
      <button type="button" onClick={handleClick}>버튼</button>
      </>
   )
}

export default EventComponent2;

 

'국비교육과정 정리 > React' 카테고리의 다른 글

[React] ContextAPI  (0) 2023.01.25
[React] React에 CSS 적용하기  (0) 2023.01.18
[React] Hook(훅)  (0) 2023.01.17
[React] Map, Filter를 이용한 컴포넌트 응용  (0) 2023.01.17
React  (0) 2023.01.15

댓글