https://react-ko.dev/reference/react/useState
1
2
3
4
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos()); // 초기화 함수
const [fn, setFn] = useState(() => someFunction); // 함수 저장
parameters
initialState
- 모든 데이터 타입 허용
- 초기 렌더링 이후 무시
- 함수를 넣을 경우, 그 함수는 순수해야하며 인자를 받지 말아야한다. 또한 반드시 어떤 값을 반환해야한다.
Returns
- 두개의 값을 지닌 배열 반환
- 첫번째는 현재 상태
- 두번쨰는
set
설정자
Caveats
useState
는 custom hook이나 컴포넌트의 최상위 레벨에서만 호출 가능하다. (반복, 조건문 안은 불가능)- Scrict Mode 에서는 디버깅을 위해 초기화함수가 두번 실행된다.
Set 함수
Parameters
nextState
- 다음 상태가 될 값 또는 업데이터 함수를 넣을 수 있음.
Caveats
set
함수는 다음 렌더링에 대한 state 변수만 업데이트한다.set
함수 호출 이후에도 호출 이전의 state 값을 얻는다.- 업데이트된 새로운 값이
Object.is
에 의해 현재state
와 동일하다고 판단되면 React는 자신과 자식컴포넌트를 리렌더링하지 않는다. set
함수는 이벤트 핸들러 내 모든 코드가 실행되고나서 일괄처리된다. 이로써 단일 이벤트 중에 여러 번 리렌더링되는 것을 막는다. 만약 더 일찍 리렌더링 되어야하면flusySync
를 사용할 수 있다.- 렌더링 도중
set
함수를 호출하는 것은 현재 렌더링 중인 컴포넌트 내에서만 호용된다. React는 해당 출력을 머리고 즉시 새로운 state로 다시 렌더링한다. 이는 이전 렌더리으이 정보를 저장하는데 사용될 수 있다 예시 참고 관련링크 - Strict Mode에서는 디버깅을 위해 업데이터 함수를 두번 호출한다. 업데이터 함수가 순수하다면 아무런 영향이 없다.
Usage
이전 state를 기반으로 state 업데이트하기
단일 이벤트 핸들러 내에서 state는 유지되므로 다음과 같이 하면 43
이 된다.
1
2
3
4
5
function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}
다음과 같이 업데이터 함수를 사용해야한다.
1
2
3
4
5
function handleClick() {
setAge(a => a + 1); // setAge(42 => 43)
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}
key로 state 재설정하기
App
에서 Form
의 key
를 지정해줌으로써, Reset 버튼이 클릭되면 key
가 변경되고 Form
의 상태는 초기화된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { useState } from 'react';
export default function App() {
const [version, setVersion] = useState(0);
function handleReset() {
setVersion(version + 1);
}
return (
<>
<button onClick={handleReset}>Reset</button>
<Form key={version} />
</>
);
}
function Form() {
const [name, setName] = useState('Taylor');
return (
<>
<input
value={name}
onChange={e => setName(e.target.value)}
/>
<p>Hello, {name}.</p>
</>
);
}
이전 렌더링에서 얻은 정보 저장하기
렌더링 중에 set
함수를 호출 하는 경우가 있다. 대부분은 필요하지 않다.
- 필요한 겂이 현재 props나 다른 state에서 모두 계산할 수 있으면 중복되는 state를 제거하라. 너무 많은 재계산이 걱정되면
useMemo
를 사용하라 - 전체 컴포넌트 트리의 state를 재설정하려면 컴포넌트에 다른
key
를 전달하라 - 가능하다면 이벤트 핸들러의 모든 관련 state를 업데이트하라
이 모든 경우에 해당되지 않는 특수한 경우로는, 이전에 렌더링 된 값을 기반으로 새로운 state를 계산하고 싶을 때다. 이때는 무한 리렌더링에 주의해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { useState } from 'react';
export default function CountLabel({ count }) {
const [prevCount, setPrevCount] = useState(count);
const [trend, setTrend] = useState(null);
if (prevCount !== count) {
setPrevCount(count);
setTrend(count > prevCount ? 'increasing' : 'decreasing');
}
return (
<>
<h1>{count}</h1>
{trend && <p>The count is {trend}</p>}
</>
);
}
일반적으로 이 패턴은 이해하기 어렵지만 Effect에서 state를 업데이트하는 것보다는 낫다. 렌더링 도중 set
함수를 호출하면 React는 컴포넌트가 return문으로 종료된 직후 자식 컴포넌트를 렌더링하기 전에 해당 컴포넌트를 리렌더링한다. 이렇게하면 자식 컴포넌트를 두번 렌더링할 필요가 없다. 관련링크