useState
는 컴포넌트에 상태 변수를 추가하는 리액트 훅이에요.
const [state, setState] = useState(initialState);
Reference | 레퍼런스
useState(initialState)
상태 변수를 선언하고 싶다면 최상위 컴포넌트에서 useState(initialState)
를 호출하세요.
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos());
// ...
}
배열을 구조분해하여 [something, setSomething]
의 형태로 상태 변수를 작성하는 것이 네이밍 컨벤션이에요.
Parameters | 파라미터
initialState
: 상태의 초기값. 타입은 상관 없으나 함수에 대한 특별한 동작이 있어요. 이 인자는 최초 렌더링 후에는 무시돼요.- 만약
initialState
로 함수를 전달한다면, 초기화 함수처럼 여겨져요. 순수함수여야하고, 인자를 받지 않아야하며, 어떤 타입의 값을 반환해야해요. 리액트는 컴포넌트를 초기화할 때 초기화 함수를 호출하고 이 함수의 반환값을 초기 상태로 저장해요. 더 많은 예시는 아래에서 살펴볼 수 있어요.
- 만약
Returns | 반환값
useState
는 정확히 두 개의 값을 배열로 반환해요.
- 현재 상태. 최초 렌더링 동안 전달한
initialState
를 매칭해요. - 다른 값으로 상태를 업데이트해주고 리렌더링을 발생시키는
set
함수.
Caveats | 주의사항
useState
는 훅이기 때문에 최상위 컴포넌트 또는 직접 만든 훅에서만 사용할 수 있어요. 반복문이나 조건문 안에서는 호출할 수 없고요. 만약 필요하다면 새로운 컴포넌트로 추출하여 그 안으로 상태를 넣으세요.- 엄격한 모드(Strict Mode)가 실행 중이라면 리액트는 의도하지 않은 불순한 요소를 찾기 위하여 초기화 함수를 두 번 호출해요.. 개발 모드에서만 이렇게 동작하고 실제 프로덕션 환경에는 영향을 미치지 않아요. 만약 초기화 함수가 순수함수라면 이 동작이 로직에 영향을 미치지 않을 거예요. 두 호출 중 하나의 결과는 무시돼요.
setSomething(nextState)
와 같은 set
함수
useState
로 반환된 set
함수는 상태를 다른 값으로 업데이트시키고 리렌더링을 발생시켜요. 직접적으로 다음 상태값을 넘겨주거나 이전 값으로 부터 다음 상태를 계산하는 함수를 전달할 수 있어요.
const [name, setName] = useState('Edward');
function handleClick() {
setName('Taylor');
setAge(a => a + 1);
// ...
}
Parameters | 파라미터
nextState
: 상태가 변하길 바라는 값. 타입은 상관 없으나 함수에 대한 특별한 동작이 있어요.- 만약
nextState
에 함수를 전달한다면 _업데이터 함수_처럼 여겨져요. 이 함수는 순수해야하고, 단일 인자로 보류한 상태를 받아요. 그리고 다음 상태값을 반환해요. 리액트는 업데이터 함수를 큐에 넣고 컴포넌트를 리렌더링해요. 다음 렌더링동안 리액트는 이전 상태에 큐에 저장된 모든 업데이터를 적용하여 다음 상태를 계산해요. 더 많은 예시는 아래에서 살펴볼 수 있어요.
- 만약
Returns | 반환값
set
함수는 반환값이 없어요.
Caveats | 주의사항
set
함수는 _다음_렌더링을 위해서만 상태 변수를 업데이트 시켜줘요. 만약set
함수를 호출한 후에 상태 변수를 읽는다면 호출하기 전에 화면에 있었던 여전히 이전 값을 얻을 거예요.- 만약
Object.js
로 비교하여 넘긴 새로운 값이 현재state
와 일치한다면, 리액트는 해당 컴포넌트와 그 자식 컴포넌트의 리렌더링을 건너뛰어요. 최적화를 시키는 거예요. 어떤 경우에 리액트는 자식 컴포넌트를 건너뛰기 전에 컴포넌트를 호출할 필요가 있을지도 모르지만 이는 코드에 영향을 미치지 않아요. - 리액트는 상태 업데이트를 일괄적으로 처리해요. 모든 이벤트 핸들러가 동작한 후에 화면을 업데이트하고 상태의
set
함수를 호출해요. 이는 단일 이벤트가 진행되는 동안 리렌더링이 여러번 되는 것을 방지해요. 거의 일어날 확률은 없지만, DOM에 접근해야하는 상황처럼 만약 리액트가 화면을 더 빠르게 업데이트를 하도록 만들어야하는 상황이라면flushSync
를 사용할 수 있어요. - 렌더링 동안
set
함수를 호출하는 것은 현재 렌더링되고 있는 컴포넌트 안에서만 허용돼요. 리액트는 그 결과를 버리고 즉시 새로운 상태로 리렌더링을 시도해요. 이러한 패턴은 거의 필요치 않으나 이전 렌더링에서 정보를 저장하기 위하여 사용할 수 있어요. 더 많은 예시는 아래에서 살펴볼 수 있어요. - 엄격한 모드(Strict Mode)가 실행 중이라면 리액트는 의도하지 않은 불순한 요소를 찾기 위하여 업데이터 함수를 두 번 호출해요.. 개발 모드에서만 이렇게 동작하고 실제 프로덕션 환경에는 영향을 미치지 않아요. 만약 초기화 함수가 순수함수라면 이 동작이 로직에 영향을 미치지 않을 거예요. 두 호출 중 하나의 결과는 무시돼요.
Usage | 용법
Adding state to a component | 컴포넌트에 상태 추가하기
한 개 이상의 상태 변수를 선언하고 싶다면 최상위 컴포넌트에서 useState(initialState)
를 호출하세요.
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(42);
const [name, setName] = useState('Taylor');
// ...
}
배열을 구조분해하여 [something, setSomething]
의 형태로 상태 변수를 작성하는 것이 네이밍 컨벤션이에요.
useState
는 정확히 두 개의 값을 배열로 반환해요.
- 현재 상태. 최초 렌더링 동안 전달한
initialState
를 매칭해요. - 다른 값으로 상태를 업데이트해주고 리렌더링을 발생시키는
set
함수.
화면에 보여지는 것을 업데이트하기 위해서는 다음 상태를 넣어서 set
함수를 호출하세요.
function handleClick() {
setName('Robin');
}
리액트는 다음 상태를 저장하고, 새로운 값으로 컴포넌트를 리렌더링 한 다음 UI를 업데이트해요.
함정함수를 호출하는 것은 이미 실행되고 있는 코드 안에서 현대 상태값을 변경하는 것이 아니에요.
setfunction handleClick() { setName('Robin'); console.log(name); // Still "Taylor"! }
이 함수는 useSate가 다음 렌더링부터 반환하는 값에만 영향을 미쳐요.
기본적인 useState 예시
1. 카운터 (숫자)
이 예시에서 count
상태 변수는 숫자에요. 버튼을 누르면 숫자가 증가해요.
2. 텍스트 필드 (문자열)
이 예시에서 text
상태 변수는 문자열이에요. 입력을 할 때, handleChange
는 가장 최근에 브라우저의 인풋 DOM 요소에서 받은 입력값을 읽고 상태를 업데이트하기 위해 setText
를 호출해요. 이는 아래에 현재 text
를 보여줄 수 있도록 만들어요.
3. 체크박스 (불리안)
이 예시에서 liked
상태 변수는 불리안 타입이에요. 인풋을 클릭하면 setListed
는 브라우저의 체크박스 인풋이 체크가 되었는지 혹은 되지 않았는지에 따라서 liked
상태를 업데이트해요.
4. 폼 (두 개의 변수)
같은 컴포넌트안에서 한개 이상의 변수를 선언할 수 있어요. 각 상태 변수는 독립적이어야해요.
Updating state based on the previous state | 이전 상태를 기반으로 하여 상태 업데이트하기
age
는 42
라고 가정할게요. 이 핸들러는 setAge(age + 1)
을 세 번 호출해요.
function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}
그러나 한 번 클릭하면 age
는 45
가 아니라 43
밖에 되지 않아요! set
함수는 이미 동작하고 있는 코드에서 age
상태 변수를 업데이트 하지 않기 때문이에요. 따라서 각각의 setAge(age + 1)
호출은 setAge(43)
이 돼요.
function handleClick() {
setAge(a => age + 1); // setAge(42 => 43)
setAge(a => age + 1); // setAge(43 => 44)
setAge(a => age + 1); // setAge(44 => 45)
}
여기서 a => a + 1
은 업데이터 함수에요. 보류하고 있는 상태 변수를 가지고 다음 상태를 계산해내요.
리액트는 업데이터 함수를 큐에 넣어요. 그리고나서 다음 렌더링에서 같은 순서로 이 함수들을 호출해요.
a => a + 1
은42
를 보류하고 있는 상태로 받고43
을 다음 상태로 반환해요.a => a + 1
은43
를 보류하고 있는 상태로 받고44
을 다음 상태로 반환해요.a => a + 1
은44
를 보류하고 있는 상태로 받고45
을 다음 상태로 반환해요.
큐에 들어간 다른 상테는 없기 때문에 리액트는 마지막에 45
를 현재 상태로 저장해요.
컨벤션에 따르면 age
를 의미하는 변수를 a
라고 한 것처럼, 보류하고 있는 상태 인자를 상태 변수 이름의 첫 번째 글자로 명명하는 것이 일반적이에요. 그러나 prevAge
나 찾기 쉬운 다른 이름으로 지어도 돼요.
리액트는 업데이터 함수가 순수한지 검증하기 위해 개발 모드에서는 함수를 두 번 실행해요.
항상 업데이터 함수를 사용하는 것이 좋나요?
설정하려는 상태가 이전 상태를 가지고 계산이 된다면 setAge(a => a+ 1)
과 같이 코드를 작성하라고 항상 들었을 거예요. 크게 문제가 되는 것은 없지만 항상 필수적인 것은 아니에요.
대부분의 경우에서 두 방법의 차이는 없어요. 리액트는 사용자가 의도한대로 동작하는지를 항상 확인해요. 이를테면 클릭과 같은 경우에는 age
상태 변수가 다음 클릭 전에 업데이트가 되었는지를 확인해요. 이는 클릭 핸들러가 이벤트 핸들러가 시작할 때 "이전의" age
를 볼 위험이 없다는 것을 의미해요.
그러나 만약 하나의 이벤트 안에서 많은 변화가 생긴다면 업데이터는 유용할 수 있어요. 또한 (리렌더링을 최적화 할 때 겪을 수 있는 일인) 상태 변수 자체에 접근하는 것이 불편한 상황에서도 유용해요.
만약 조금 더 자세한 구문을 사용하여 일관성을 유지하고 싶다면, 설정하려는 상태가 이전의 상태에서 계산될 때는 항상 업데이터 함수를 사용하는 것이 합리적이에요. 만약 다른 상태변수의 이전 상태에서 계산이 된다면, 이들을 하나의 객체로 결합하고 리듀서를 사용하세요.
업데이터를 전달하는 것과 다음 상태를 직접 전달하는 것의 차이
Updating objects and array in state | 상태의 객체와 배열 업데이트하기
상태에 객체나 배열을 넣을 수 있어요. 리액트에서 상태는 읽기만 가능한(read-only) 변수로 여겨지기 때문에 존재하는 객체를 변경하는 것이 아니라 그것을 대체해야해요. 예를 들어 만약 상태 안에 form
객체가 있다면 그것을 변경하지 마세요.
// 🚩 아래와 같이 상태의 객체를 변경하지 마세요.
form.firstName = 'Taylor';
대신, 객체를 새로 생성하여 전체 객체를 대체하세요.
// ✅ 새로운 객체로 상태를 대체하세요.
setForm({
...form,
firstName: 'Taylor'
});
더 알아보고 싶다면 상태의 객체 업데이트하기와 상태의 배열 업데이트하기를 읽어보세요.
객체나 배열을 상태로 갖는 예시
1. 폼 (객체)
이 예시에서 form
상태 변수는 객체를 갖고 있어요. 각각의 입력창은 전체 폼의 다음 상태로 setForm
을 호출하는 체인지 핸들러를 가지고 있어요. 스프레트 구문인 { ...form }
은 상태 객체가 변경되지 않고 대체된다는 것을 보장해요.
2. 폼 (중첩 객체)
이 예시에서 상태는 더욱 중첩되어 있어요. 중첩 상태를 업데이트 할 때, 업데이트하려는 객체와 그 위에 존재하는 해당 객체를 포함하는 모든 객체에 대한 복사본을 모두 만들어야해요. 더 알고 싶다면 중첩 객체 업데이트 하기 문서를 읽어보세요.
3. 리스트 (배열)
이 예시에서 todos
상태 변수는 배열을 갖고 있어요. 각 버튼 핸들러는 배열의 다음 버전으로 setTodos
를 호출해요. 스프레드 구문인 [...todos]
와 todos.map()
, todos.filter()
는 상태 배열이 변경되는 것이 아니라 대체된다는 것을 보장해요.
4. Immer를 사용하여 간결한 업데이트 로직 작성하기
만약 배열과 객체를 변경 없이 업데이트 하는 것이 지루하게 느껴진다면 Immer와 같이 반복적인 코드를 줄여주는 라이브러리를 사용할 수 있어요. Immer는 객체를 변경하는 것처럼 간결하게 코드를 작성할 수 있도록 해주지만 내부적으로는 불변적인 업데이트를 수행해요.
Avoiding recreating the initial state | 초기 상태 재생성을 피하기
리액트는 초기 상태를 처음에 한 번 저장하고 다음 렌더링부터는 무시해요.
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos());
// ...
createInitialTodos()
의 결과가 초기 렌더링에 사용되었음에도 불구하고 매 렌더링마다 이 함수를 호출하고 있어요. 만약 큰 배열이나 비싼 연산을 수행한다면 이는 낭비적이에요.
이를 해결하기 위해서는 useState
에 초기화 함수를 전달하세요.
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos);
// ...
함수 자체인 createInitialTodos
를 전달하는 것은 함수를 실행한 결과값인 createInitialTodos()
가 아니라는 것을 명심하세요. 만약 useState
에 함수를 전달한다면 리액트는 초기화 작업을 하는 동안에만 이 함수를 호출해요.
리액트는 초기화 함수가 순수한지 검증하기 위해 개발 모드에서는 함수를 두 번 실행해요.
초기화 함수를 전달하는 것과 직접 초기 상태를 전달하는 것의 차이
Resetting state with a key | 키를 사용하여 상태 리셋하기
리스트를 렌더링할 때 key
속성과 종종 마주칠 거예요. 그러나 이는 다른 목적을 수행해요.
다른 key
를 컴포넌트에 전달하여 컴포넌트의 상태를 리셋할 수 있어요. 이 예시에서 리셋 버튼은 version
이라는 상태 변수를 바꾸고 Form
에 key
로 전달해요. key
가 바뀌면 리액트는 Form
컴포넌트(와 모든 자식들)을 스크래치에서 재생성하기 때문에 상태는 리셋돼요.
더 알고 싶다면 상태 보존하고 리셋하기를 읽어보세요.
Storing information from previous renders | 이전 렌더링에서 정보 저장하기
보통은 이벤트 핸들러에서 상태를 업데이트해요. 그러나 드물게는 렌더링에 맞추어 상태를 조정할 때도 있어요. 예를 들면 prop이 바뀌었을 때 상태 변수를 바꾸는 것처럼요.
대부분의 경우에서는 이 방법이 필요하지 않아요.
- 만약 현재 props나 다른 상태에서 필요한 값을 통째로 계산될 수 있다면 불필요한 상태를 전부 삭제하세요. 만약 재연산이 너무 자주 일어날까봐 걱정된다면
useMemo
훅이 도움이 될 거예요. - 만약 전체 컴포넌트 트리의 상태를 리셋하고 싶다면 다른
key
를 컴포넌트에 전달하세요. - 만약 할 수 있다면 이벤트 핸들러 안의 관련있는 모든 상태를 업데이트하세요.
이 중 아무것도 적용할 수 없는 아주 드문 상황에서는 컴포넌트를 렌더링하는 동안 set
함수를 호출하여 지금까지 렌더링된 값에 기반하여 상태를 업데이트하는 패턴이 있어요.
아래가 바로 그 예시에요. 이 CountLabel
컴포넌트는 전달받은 count
prop을 보여줘요.
export default function CountLabel({ count }) {
return <h1>{count}</h1>
}
카운터가 이전 변화에서 증가하는지 감소하는지를 보여주고 싶다고 해볼게요. count
prop은 이것을 말해주지 않기 때문에 이전 상태를 추적할 필요가 있어요. 추적을 하기 위해 prevCount
라는 상태 변수를 추가하세요. count가 증가했는지 감소했는지를 알고 있는 trend
상태 변수를 추가하세요. prevCount
와 count
를 비교하고 만약 같지 않다면 prevCount
와 trend
를 업데이트하세요. 이제 현재 count prop과 *마지막 렌더링과 어떻게 달라졌는지를 모두 볼 수 있어요.
만약 set
함수를 렌더링하는 동안 호출한다면 prevCount !== count
와 같은 조건문 안에 있어야만 하고, setPrevCount(count)
와 같이 호출되어야만 한다는 것을 기억하세요. 그렇지 않다면 컴포넌트는 무한 렌더링에 빠져요. 또한 이처럼 현재 렌더링하고 있는 컴포넌트의 상태만을 업데이트할 수 있어요. 렌더링을 하는 동안 다른 컴포넌트의 set
함수를 호출하는 것은 에러를 발생시켜요. 마지막으로 set
함수는 여전히 변경(뮤테이션) 없이 상태를 업데이트 해야하며 이는 순수 함수의 다른 규칙을 어기지 않는다는 것을 의미해요.
이 패턴은 이해하기 어렵고 피하는 것이 좋아요. 그러나 이펙트 안에서 상태를 업데이트하는 것보다는 좋아요. 렌더링을 하는 동안 set
함수를 호출한다면 리액트는 return
문으로 컴포넌트가 나온 직후이자 자식 컴포넌트가 렌더링 되기 이전에 해당 컴포넌트를 리렌더링해요. 이 방법에서 자식 컴포넌트는 두 번 렌더링될 필요가 없어요. 컴포넌트의 남은 함수는 여전히 실행돼요. (그리고 결과는 버려져요.) 만약 조건이 모든 훅 호출하는 것보다 뒤에 있다면 렌더링을 더 일찍 시작하기 위해 미리 return;
을 넣어주세요.
Troubleshooting | 트러블슈팅
I’ve updated the state, but logging gives me the old value | 상태를 업데이트했는데 이전 값이 로그에 찍혀요.
set
함수를 호출하는 것은 *동작중인 코드 안에서 상태를 바꾸는 것이 아니에요.
function handleClick() {
console.log(count); // 0
setCount(count + 1); // 1로 리렌더링하라고 요청했는데,
console.log(count); // 하지만 여전히 0이 찍혀요!
setTimeout(() => {
console.log(count); // Also 0!
}, 5000);
}
이는 상태가 스냅샷처럼 작동하기 때문이에요. 상태를 업데이트하는 것은 새로운 값으로 리렌더링하는 것을 요청하지만 이미 실행 중인 이벤트 핸들러 안에 있는 count
라는 자바스크립트 변수에는 영향을 미치지 않아요.
만약 다음 상태를 사용할 필요가 있다면 set
함수에 전달하기 전에 변수로 이 값을 저장하세요.
const nextCount = count + 1;
setCount(nextCount);
console.log(count); // 0
console.log(nextCount); // 1
I’ve updated the state, but the screen doesn’t update | 상태를 업데이트했지만 화면은 업데이트가 안돼요.
리액트는 Object.js
로 비교한 결과, 만약 다음 상태가 이전의 상태와 동일하다면 업데이트를 무시해요. 이는 보통 객체나 배열을 상태 안에서 직접적으로 수정하면 발생해요.
obj.x = 10; // 🚩 잘못된 코드 : 존재하는 객체를 수정했어요.
setObj(obj); // 🚩 아무것도 하지 않아요.
이미 존재하는 obj
객체를 변경하고 setObj
로 다시 전달했기 때문에 리액트는 업데이트를 무시해요. 이를 해결하려면 상태의 객체와 배열을 변경하지 말고 이들을 대체한다는 것을 항상 보장해야해요.
// ✅ 올바른 코드 : 새로운 객체 생성하기
setObj({
...obj,
x: 10
});
I’m getting an error: “Too many re-renders” | "너무 많은 리렌더링이 발생해요."라는 에러가 떠요.
너무 많은 리렌더링이 발생해요. 리액트는 무한 반복을 방지하기 위해 렌더링의 횟수를 제한해요.
라는 에러를 봤을 거예요. 일반적으로 이 메시지는 렌더링을 하는 동안 무조건적으로 상태를 설정하고 있어서 컴포넌트가 렌더링, (렌더링을 유발하는) 상태 설정, 렌더링, (렌더링을 유발하는) 상태 설정을 계속 수행하고 있다는 것을 의미해요. 이 에러는 이벤트 핸들러를 지정하면서 실수를 했기 때문에 발생하는 경우가 많아요.
// 🚩 잘못된 코드 : 렌더링 동안 핸들러를 호출했어요.
return <button onClick={handleClick()}>Click me</button>
// ✅ 올바른 코드 : 이벤트 핸들러를 전달했어요.
return <button onClick={handleClick}>Click me</button>
// ✅ 올바른 코드 : 인라인 함수를 전달했어요.
return <button onClick={(e) => handleClick(e)}>Click me</button>
만약 이 에러의 원인을 찾을 수 없다면 콘솔에서 에러 옆에 있는 화살표를 클릭하고 에러를 유발하는 구체적인 set
함수 호출을 찾기 위해 자바스크립트 스택을 살펴보세요.
My initializer function runs twice | 초기화 함수가 두 번 실행돼요.
엄격한 모드에서 리액트는 일부 함수를 한 번이 아니라 두 번 실행해요.
function TodoList() {
// 이 컴포넌트 함수는 매 렌더링에서 두 번씩 실행돼요.
const [todos, setTodos] = useState(() => {
// 이 초기화 함수는 초기화 작업 동안 두 번 실행돼요.
return createTodos();
});
function handleClick() {
setTodos(prevTodos => {
// 이 업데이터 함수는 클릭할 때마다 두 번씩 실행돼요.
return [...prevTodos, createTodo()];
});
}
// ...
이는 예상된 일이며, 코드를 깨뜨리지 않아요.
이 개발 모드에서만 실행되는 동작은 컴포넌트를 순수하게 만들어줘요. 리액트는 이 호출 중 하나의 결과만을 사용하고 다른 호출의 결과는 무시해요. 컴포넌트, 초기화 함수 그리고 업데이터 함수가 순수한 한, 이 실행이 로직에 영향을 미치지 않아요. 하지만 의도치 않게 이들이 순수하지 않다면 이 실행이 실수를 알아채도록 도와줘요.
예를 들어, 이 불순한 업데이터 함수는 상태에서 배열을 변경해요.
setTodos(prevTodos => {
// 🚩실수 : 상태 변경
prevTodos.push(createTodo());
});
리액트는 업데이터 함수를 두 번 호출하기 때문에 할 일(todo)가 두번 추가되는 것을 확인할 수 있고 실수가 있다는 것을 알게 돼요. 이 예시에서 배열을 변경하는 대신 대체하는 것으로 실수를 해결할 수 있어요.
setTodos(prevTodos => {
// ✅ 올바른 코드 : 새 상태로 대체하기
return [...prevTodos, createTodo()];
});
이제 이 업데이터 함수는 순수하지만 추가적으로 이 함수를 호출하는 것이 동작 자체의 차이를 만들진 않아요. 이것이 바로 리액트가 함수를 두 번 호출하는 것이 실수를 찾는 것을 도와주는 이유예요. 컴포넌트, 초기화 함수 그리고 업데이터 함수만 순수하면 돼요. 이벤트 핸들러는 순수할 필요가 없기 때문에 리액트는 절대 이벤트 핸들러를 두 번 호출하지 않아요.
더 알고싶다면 컴포넌트를 순수하게 유지하기 문서를 읽어보세요.
I’m trying to set state to a function, but it gets called instead | 상태를 함수로 설정하려고 하는데 호출이 돼요.
아래와 같이 상태에 함수를 넣을 수는 없어요.
const [fn, setFn] = useState(someFunction);
function handleClick() {
setFn(someOtherFunction);
}
함수를 전달했기 때문에 리액트는 someFunction
이 초기화 함수라고 생각하고 someOtherFunction
은 업데이터 함수라고 생각해요. 그래서 리액트는 이 함수들을 호출하고 결과를 저장해요. 실제로 함수를 _저장_하려면 () =>
를 양쪽 모두에 넣으세요. 그러면 리액트는 전달한 함수 자체를 저장할 거예요.
const [fn, setFn] = useState(() => someFunction);
function handleClick() {
setFn(() => someOtherFunction);
}
'리액트 공식문서 | React Docs > Reference > react@18.2.0' 카테고리의 다른 글
[Hooks] useTransition | useTransition 훅 (1) | 2024.02.07 |
---|---|
[Hooks] useSyncExternalStore | useSyncExternalStore 훅 (1) | 2024.02.07 |
[Hooks] useRef | useRef 훅 (0) | 2024.02.04 |
[Hooks] useReducer | useReducer 훅 (1) | 2024.02.04 |
[Hooks] useOptimistic | useOptimistic 훅 (0) | 2024.02.03 |