2024.02.01(목)
useState
Hook은 다음 두 가지를 제공useState
Hook 사용법import { useState } from 'react';
const [state, setState] = useState(initialState);
initialState
에 저장하고 싶은 data의 초기값을 지정 (첫번째 rendering때 이 값이 반환되는 state 변수에 담기고 그 이후의 rendering에서는 무시됨)useState
는 stateful value와 이를 업데이트할 수 있는 function을 배열 형태로 반환💡 state 변수는 구조분해할당을 이용해
[something, setSomething]
으로 이름을 짓는 naming convention이 존재
setSomething(nextState)
와 같이 같이 사용set 함수는 반환값은 없고 인자로 next state를 바로 전달(“just replacing it”)할 수도 있고, 이전 state에서 값을 계산하는 updater function을 전달(“do something with the state value”)할 수 있음
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(42);
const [name, setName] = useState('Taylor');
function handleClick() {
setName('Swift'); // 다음 값을 직접 전달
setAge(a => a + 1); // updater function 전달
// ...
updater function을 전달하는 경우에는 보류 상태(pending state)를 유일한 인수로하고 next state를 반환하는 순수함수를 사용해야 함
💡 updater function의 인수(argument)명에 대한 naming convention
- 해당 state variable의 첫 글자들로 짓기
setEnabled(e => !e); setLastName(ln => ln.reverse()); setFriendCount(fc => fc * 2);
- 좀 더 자세한 코드를 선호하거나 일반적인 경우에는 state variable 이름 전체를 그대로 사용할 수 있음
setEnabled(enabled => !enabled); setEnabled(prevEnabled => !prevEnabled); // prefix 사용
Object.is
비교를 통해 next state가 previous state와 같은지 비교하고 같은 경우 update를 무시함 🔗Object.is
로 객체를 비교하면 참조값만을 비교하기 때문에 state variable을 직접 수정하고 이를 set 함수에 전달하더라도 React는 변경 사항을 알 수 없고 update가 되지 않음avoid (mutates the array) | prefer (returns a new array) | |
---|---|---|
adding | push , unshift | concat , [...arr] spread syntax (example) |
removing | pop , shift , splice | filter , slice (example) |
replacing | splice , arr[i] = ... assignment | map (example) |
sorting | reverse , sort | copy the array first (example) |
💡 참고로 spread 문법은 1 level depth의 요소들만 복사하는 shallow copy가 수행되기 때문에 깊이가 깊은 객체들은 spread 문법을 여러 번 사용하여 deep copy를 수행해야 함 🔗
const [person, setPerson] = useState({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); // Updating a nested object setPerson({ ...person, // Copy other fields artwork: { // but replace the artwork ...person.artwork, // with the same one city: 'New Delhi' // but in New Delhi! } });
“Rendering” means that React is calling your component, which is a function.
해당 함수에서 반환하는 JSX는 rendering되는 시점의 snapshot과 같음!
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}>+3</button>
</>
)
}
<button onClick={() => {
setNumber(0 + 1);
setNumber(0 + 1);
setNumber(0 + 1);
}}>+3</button>
리액트는 효율적인 rendering을 위해 state 업데이트를 이벤트 핸들러의 실행이 완료된 후에 일괄 처리함(batching)
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
// 다음 세 번의 setNumber를 각각 처리하지 않고 queue에 모아서 일괄 처리 -> 버튼을 누르면 3씩 증가
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
alert(number);
}}>+3</button>
</>
)
}
setNumber
는 queue로 들어가고 alert
가 가장 먼저 실행됨setNumber
들을 일괄 처리해서 3으로 증가하게 됨A JavaScript function that you can sprinkle with markup
<section>
<Profile />
→ component Profile
호출