updated 03/09/23
리액트에서 상태(state) 값은 매우매우 중요하다.
화면에서 일어나는 모든 변화들은 변수(state) 안에 담아서 표현될 수 있고, 업데이트도 자주 일어나기 때문에
렌더링(a.k.a 새로고침) 되면서 항상 최신 데이터(a.k.a state)를 유지해야 한다.
너무너무 기본이지만 확실히 알고 넘어가고자 공식문서를 참고하여 한번 더 정리해보았다.
React(93) useState 알아보기 (공식문서정리)
useState 는 리액트 내장 함수이고, state 를 나타내는 변수로 사용할 수 있다.
useState 는 리액트 훅이기 때문에 컴포넌트 최상단에서 호출하여야 한다. 조건문이나 반복문에서의 사용은 안된다.
(strict 모드에서는 pure func 인지 검사을 위해 2번 실행이 된다. 하지만 프로덕션에서는 영향을 미치지 않는다.)
// inititalState 를 넣어주면 첫 렌더시에만 name에 'Dongmin' 이라는 값이 들어간다
const [name, setName] = useState('Dongmin');
↑
initialState
useState의 매개변수로는 initialState 가 있다. 최초 렌더시 들어갈 값(any type)을 넣어준다.
useState 의 리턴 값으로는 구조분해할당을 해서 [value, setValue] ←←←얘네들을 꺼내서 사용한다
- value 는 현재 상태값이다. 첫렌더시에 initialState 를 보여준다.
- setValue 는 value 를 다른 값으로 업데이트할 때 사용한다. 또한 리렌더링의 트리거 역할을 한다.
set function
setValue의 매개변수로는 모든 타입의 값(any type)을 받을수 있다. 심지어 함수도 가능하다.
(함수로 받으려면 퓨어해야 되고, state를 리턴값으로 내보내야 한다. 엄청 권장하진 않는 느낌)
(리액트는 이 updater 함수를 큐에 넣어놓고, 컴포넌트를 리렌더한다.)
setValue 는 다음 렌더시에 value 를 업데이트 한다.
그렇기 때문에 setValue 함수를 실행한다고 해서 value 가 바로 바뀌거나 하지는 않는다.
현재 value 와 업데이트 value 가 똑같으면 리액트는 리렌더하지 않는다.
value 업데이트를 일괄처리(batch) 한다.
모든 이벤트 핸들러와 그 set function 이 호출되고 난 후 화면을 업데이트 한다.
그래서 하나의 이벤트가 일어나는 동안 여러 번 리렌더되는 것을 막을 수 있다.
setValue를 리렌더 동안 호출하는 것은 현재 렌더링되는 컴포넌트 내에서만 가능하다.
원래 리턴값을 급취소하고, 새로운 value 의 리턴값으로 바꿔 렌더링한다. (rarely needed)
useState 사용하기
Adding state to a component
리액트는 변경한 state를 저장하며, 컴포넌트를 new value 로 렌더하고, ui 를 업데이트 한다.
→ React will store the next state, render your component again with the new values, and update the UI.
Updating state based on the previous state
setValue 를 여러번 사용하면 변경된 value 값으로 업데이트 될 것이라고 예상하지만 아니다.
왜냐하면 setValue 를 여러번 호출한다고해서 즉각적인 변수의 업데이트로 이어지지는 않기 때문이다.
→ This is because calling the set function does not update the age state variable in the already running code.
function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}
setValue안에 updater function 을 넣어주면 문제가 해결된다.
렌더링하게 되면 내부적으로 큐에서 pending state 로 들고 있어 그걸 바탕으로 next state 를 계산하게 된다.
→ your updater function. It takes the pending state and calculates the next state from it.
→ React puts your updater functions in a queue. Then, during the next render, it will call them in the same order:
function handleClick() {
setAge(a => a + 1); // setAge(42 => 43) 42를 pending state로 받고 43을 리턴한다
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}
Updating objects and arrays in state
state 안에 객체나 배열을 넣을 수 있다. 하지만 그냥 값을 바꿀 수 는 없다. (read-only)
setState 함수를 이용해 값을 변경해줘야한다.
const [obj, setObj] = useState({ name: 'saebal'});
obj.name = 'John'; // 🙅♂️ 틀렸다 직접 바꾸면 안된다.
setObj({...obj, name: 'John'}); // 🙆♂️ 정답 직접 바꾸어주어야 한다.
Avoiding recreating the initial state
initialState 를 첫 렌더만 저장하고 다음 렌더부터는 무시한다.
만약 initialState 를 함수로 받는다면? 아무리 초기값으로 넣었다고 하더라도 함수는 모든 렌더마다 호출될 것이다.
const [todos, setTodos] = useState(createFirstTodos()); // 🙅♂️ 함수가 호출된 결과 값이 항상 나온다.
const [todos, setTodos] = useState(createFirstTodos); //🙆 함수자체가 불리고 첫렌더에만 실행된다.
createFirstTodos() 는 호출되어 실행된 결과값이 나오지만,
createFirstTodos 는 function 으로 시작하는 함수 그자체 코드를 호출한다.
리액트에서는 initialState 로 createFirstTodos 를 받으면 첫렌더에만 실행이 된다.
부끄럽지만 다시 되새김질해보는 지난날의 기록 🐥 ↓ ↓ ↓
'React' 카테고리의 다른 글
React(96) useContext 로 상태값 관리하기 (0) | 2023.06.01 |
---|---|
React(95) 리스트 더보기 기능 구현 (0) | 2023.04.25 |
React(93) TypeScript - 유사객체배열에서 원하는 값 사용하기 (0) | 2023.02.16 |
React(92) useRef 알아보기 (공식문서 정리) (0) | 2023.02.01 |
React(91) 탭 클릭시 지정 영역으로 스크롤 이동 / 스크롤시 해당 탭 자동선택 (0) | 2023.01.25 |
댓글