Hooks가 제공하는 내장 API(즉, 기본 Hook들에는 useState, useEffect, useContext가 있다.)
1️⃣: 최초로 렌더링 하는 동안, 반환된 state는 첫번째 전달된 인자(initialValue)의 값과 같음
2️⃣: setState 함수는 state 갱신할때(바뀔때!!!!) 사용함. 새 state 값 받아서 컴포넌트 리렌더링을 큐(대기줄이라고 생각하자)에 등록!
3️⃣: 다음 리렌더링 시에 useState를 통해 반환받은 첫번째 값은 항상 최신 state가 됨(클래스형 컴포넌트에서 setState 하면 병합되지만, 함수형 컴포넌트에서는 이전 상태값 지움)
import React, { useState } from "react";
//useState라는 메서드를 이용해서 사용할거니까 react import 해줘야함!
/*
useState() 리액트 메서드!
- 배열을 반환함
- 배열의 비구조화 할당 통해서 count(값으로 사용), setCount(상태변화함수)
- setCount로 상태를 변화시킬수(업데이트) 할수 있다는 뜻!
- useState(숫자)=> 숫자는 초기값!
*/
const Counter = () => {
const [count, setCount] = useState(0); // 초기화 해준것
// 버튼 누르면 증가, 감소하는 함수 만들어서 onclick 이벤트로 추가해줘야함
const onIncrease = () => {
setCount(count + 1); //++은 안됨
};
const onDecrease = () => {
setCount(count - 1);
};
/*
0에서 출발 -> 1씩 증가하고 -> 1씩 감소하는 : count 상태!
*/
return (
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
{/* 카멜케이스로사용하고, {}에 함수이름 넣으면된다! */}
<button onClick={onDecrease}>-</button>
</div>
);
};
=> 빈배열이라면, 처음 마운팅 될때만 실행!
import React, { useEffect, useState } from "react";
const LifeCycle = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
/* 컴포넌트가 mount(시작) 되는 시점 제어 */
useEffect(() => {
console.log("Mount!");
}, []);
/*카운트를 입력해도, mount 안찍히는걸 보면
두번째 인자에 [](빈배열)넣어주고, 첫번째 인자에 콜백함수(안에 수행하고싶은 코드 넣어주기)
*/
/* 컴포넌트가 업데이트 되는 시점 제어 : 두번째 인자 작성 안하기*/
useEffect(() => {
console.log("Update!");
});
/* dependency array의 값이 변화할때마다 찍히는 시점
=> 즉 잘 활용하면 감지하고 싶은 값이 변화하는 순간에만 콜백함수 수행할 수 있다는 말
*/
useEffect(() => {
console.log(`${count}번째 업데이트`);
if (count > 5) {
alert("count는 5를 넘을 수 없습니다. 따라서 1로 초기화 합니다.");
setCount(1); //바꿔주고 싶은 값을 입력하면됨
}
}, [count]);
useEffect(() => {
console.log(`text is update : ${text}`);
}, [text]);
return (
<div style={{ padding: 20 }}>
<div>
{count}
<button onClick={() => setCount(count + 1)}>+</button>
<div>
<input value={text} onChange={(e) => setText(e.target.value)}></input>
</div>
</div>
</div>
);
};
export default LifeCycle;
import React, { useState, useEffect } from "react";
export const Timer = () => {
useEffect(() => {
const timer = setInterval(() => {
console.log("타이머 돌아가는중..");
}, 1000);
//useEffect의 리턴값으로 정리할 함수를 써주면됨!(unMount, 즉 화면에서 사라질때 실행)
return () => {
clearInterval(timer);
console.log("타이머 종료");
};
}, []);
return (
<>
<span> 타이머를 시작합니다. 콘솔을 보세요!</span>
</>
);
};
const UesEffect = () => {
const [toggle, setToggle] = useState(false);
const handleTogle = () => {
setToggle(!toggle);
};
return (
<div>
{toggle && <Timer />}
<button onClick={handleTogle}>Toggle Timer</button>
</div>
);
};
export default UesEffect;
1) dependency가 없는 방법
=> 어떤 state의 변수든, 값이 변경된것 인지하고 실행함(업데이트 될때마다 실행)
2) 대괄호 이용
=> 처음 mount 되는 시점만 실행!
3) 대괄호 안에 특정 변수(들)을 지정하는 방법
=> 대괄호 안에 지정된 변수 혹은 오브젝트가 변하지 않으면 useEffect는 실행되지 않는다.
=> 복사본을 만들어서 사용해야한다.(참조타입은 콜스텍에 메모리힙의 주소만을 저장하고 메모리 힙에 저장, 변경되기 때문에!) , 얕은 복사와 깊은 복사와 관련있다!
=> 간단하게 요약하면 리액트 상태 업데이트의 원리 때문임.
=> batch라는 특징