미새문지

react Hook함수(1) State(1) 본문

웹 프론트엔드

react Hook함수(1) State(1)

문미새 2022. 7. 31. 03:42
728x90

Hook함수란?

 

react에서 상태 변경, 즉 가상돔의 상태를 변경할 수 있는 함수이며
그에 따른 생명 주기를 통해 다양한 이벤트를 실행할 수 있는 함수입니다

 

react의 초기 상태는 Class형 컴포넌트를 사용했었습니다

지금의 컴포넌트가

const 컴포넌트명 = () => {
	...
}

이라면, 옛날의 컴포넌트는

Class 컴포넌트명 extends Components {
	...
}

이런 방식이였습니다

 

이 클래스 컴포넌트에는 라이프 사이클이라는게 있었는데 이 생명주기(라이플사이클)

페이지가 처음 열렸을 때부터 닫혔을 때까지 사이에 일어나는 이벤트나 값 변경 등을 관리합니다

 

Class는 다양한 기능을 상용할 수 있으나 기계와 사용자들을 혼동시킵니다

숙련된 React 개발자조차도 Class를 통한 React의 이해는 완벽하게 하기 힘들었습니다

 

이후에 함수형으로 React를 만들어보자 하여 함수형 컴포넌트가 생겼기 때문에, 자연스럽게

생명주기(라이프 사이클)이 사라지고 Hook 함수가 등장했습니다

 

1. useState
- Hooks의 상태 관리 함수
- 컴포넌트에서 바뀌는 값을 관리
- 값이 바뀐 것을 감지하여 리랜더링
- 값이 바뀌는 것을 감지하여 리랜더링 시켜줘야할 필요가 있을 때 사용하는 변수

 

 

이제 hook폴더를 만들어 안에 기본 리액트 세팅을 완료하고 작성합니다src안에 componentspages폴더를 만들고 pages폴더 안에 hook.js파일을 만듭니다

 

const Hook = () => {
    return(
    );
}
export default Hook

hook파일 내용을 기본적인 함수로 만들어줍니다

 

App.js 파일에는 Hook함수를 연결해 출력시켜야하기 때문에 컴포넌트 해줍니다

import './App.css';
import Hook from './pages/hook';

function App() {
  return (
    <Hook/>
  );
}

export default App;

 

다음 components 폴더에 state.js를 만들어 작성해줍니다

import {useState} from "react"

const State = () => {
  	const [state, setState] = useState("state 처음 시작");
  
  	return(
    	<div>
        	{state}
        </div>
    )
 }
 export default State;

State 변수를 작성하고 State라는 변수가 지정이 안되있으니 import해주는데

import { useState, useRef } from "react" 는 이미 지정되있는 "react"에서 useState를 가져와라 라는 뜻입니다

변수의 내용은 useState의 작성한 값이 state 안으로 들어가져서 그 변수를 직접 사용할 수 있어 div안에 넣었습니다

 

const[변수명, 변수 값을 바꿔줄 함수명] = useState(변수의 기본값)

 

state 함수 안에 함수하나를 더 만들어줍니다

import {useState} from "react"

const State = () => {
  	const [state, setState] = useState("state 처음 시작");
    
    const onChangeText = () => {
    	setState("두번째 시작하는 state")
    }
  
  	return(
    	<div onClick={onChangeText}>
        	{state}
        </div>
    )
 }
 export default State;

함수를 만들고 변수를 onClick했을때의 값에 넣어줍니다

 

setState는 ("값")을 넣으면 변수의 값이 바뀝니다 즉, div를 클릭했을 때 안의 값이 변하는거죠

 

이 상태로 웹브라우저를 실행해보면 클릭했을 시

 

 

로 바뀌는 것을 볼 수 있습니다

 

-------------------------------------------------------------------------------------------------------------------

< state의 불변성 >

state는 변하지 않아야한다

 

const obj = {}

const obj2 = {} 일 때

 

obj === obj2 는 과연 true일까 false일까서로 주소값이 달라 false가 나옵니다

단, const obj3 = obj 는 obj3과 obj가 같은 참조 값을 가지게 됩니다

이런 이미지의 형태가 되는데 이것은 obj의 값을 obj3에 복사를 시켜 같은 주소값을 가지게 하는거죠

obj의 값에 1을 넣으면 obj3의 값도 똑같이 1이 됩니다

따라서 obj가 가지고 있는 객체값이 변경되면 obj3도 같은 객체를 가지고 있어 값이 변경됩니다

즉, obj 원본데이터의 훼손은 obj3에도 적용이 되어 예상치 못한 오류와 버그를 일으킵니다 ( 참조 오류)

 

- 얕은 복사의 에러를 해결하기 위해 깊은 복사를 실현

1. spread operator (...)

2. const a = state   --->  a의 변조과정  --->  setState(a)

3. immer.js와 같은 라이브러리를 이용(리덕스)

 

const [state, setState] = useState([
    {
      	id: 1,
      	name: "문미새",
    },
    {
      	id: 2,
      	name: "김미새",
    },
    {
      	id: 3,
      	name: "하미새",
    },
]);

예시로 이런 state의 값이 있다고 하면, 이 배열에 id:4, name: 최미새 라는 객체 값을 추가하려면 어떻게 해야 할까요 (랜더링이 일어나야 한다)

 

위의 1번 2번 방식으로 알아보겠습니다

 

1. setState([...state, {id:4, name:"최미새"}])

 - ...state로 state값을 복사해온 후에 { id:4, name: 최미새 } 값을 추가하는 방식

 

2. const arr = state

         arr.push = {id:4, name:"최미새"}

         setState(arr)

 - state값을 그대로 가져와 arr 배열에 집어넣고 { id:4, name: 최미새 }값을 배열에 넣어서 출력하는 방식

 

두 가지 방식이 존재합니다

이 중에 1번을 더 자주쓰이고 1번을 써야 합니다

2번 방법은 위에서 말했던 참조오류가 발생할 수 있기 때문입니다

 

그리고 const [state, setState] = useState([ 이 부분에서 state, setState부분은 인덱스로 가지고 오기 때문에 이름을 내가 원하는 대로 바꿔도 괜찮습니다. 대신에 순서는 바뀌지 않습니다

 

위의 코드에 onClickEvent를 추가해줄겁니다

const [state, setState] = useState([
    {
      	id: 1,
      	name: "문미새",
    },
    {
      	id: 2,
      	name: "김미새",
    },
    {
      	id: 3,
      	name: "하미새",
    },
]);

const onClickEvent = (idValue, nameValue) => {
	setState([...state, {id: idValue, name: nameValue}])
}

변수를 바꾸는 함수명을 onClickEvent 함수에 넣어 1번형식으로 깊은복사를 합니다

코딩하면서 코드가 여러종류로 묶여 복잡해질 수 있는데,

세번 째 방식인 immer.js와 같은 라이브러리를 사용하면 하위 선택자로 가지고 와도 깊은 복사가 유지되어 복잡한 구조에서는 실제로 많이 사용하는 방식입니다

 

그리고 아까 state 설명에 사용한 return 함수를 수정해줍니다

return(
	{state.map((item) => (
        <div>
        	{item.id}. {item.name}
            <button>삭제</button>
        </div>
    ))}
)

 

한줄한줄 읽으면서 map이라는 변수를 item에 담는다는 뜻이며, item이름은 아무거나 설정할수 있습니다.

상단의 name 변수들을 map으로 돌려 첫 줄부터 읽기 시작합니다

 

첫 줄은 id:1, name:"김성용" 따라서 item으로 첫줄을 가져와  {item.id}. {item.name}에 넣어주는 것이라 마지막줄까지 순서대로 읽어 받아오는거죠

 

728x90

'웹 프론트엔드' 카테고리의 다른 글

react Hook함수(2) UseRef, useMemo, useCallback  (1) 2022.08.02
react Hook함수(1) State(2)  (1) 2022.07.31
react 삼항연산자, props, 비구조화 할당  (1) 2022.07.28
react 컴포넌트  (1) 2022.07.25
react 기본 이론  (1) 2022.07.20