사용교재 : 벨로퍼트와 함께하는 모던 리액트
범위 : 1.10 ~ 1.20
노션 용량문제로 Migration
특정 DOM을 선택할 때 사용하는 Hook
함수로, 열린 태그의 ref
속성을 통해 사용.
useRef()
로 Ref
객체 생성 → 선택할 DOM에 ref
값으로 설정 → .current
값은 선택한 DOM을 가리킴
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: ''
});
const nameInput = useRef();
const { name, nickname } = inputs;
const onChange = e => {
const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
setInputs({
...inputs,
[name]: value
});
};
const onReset = () => {
setInputs({
name: '',
nickname: ''
});
nameInput.current.focus();
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
map()
을 통해 동적으로 값을 전개하여 렌더링
return (
<div>
{users.map(user => (
<User user={user} key={user.id}/>
))}
</div>
);
key : 리액트에서 배열을 렌더링 할 때 반드시 설정해야하는 props. key
값은 각 원소의 고유값으로 설정.
→ key
가 있어야 배열이 업데이트 될 때 렌더링이 효율적
(?) key
유무
key
있다key
없다useRef
의 변수 관리useRef
로 컴포넌트 안에서 조회/수정 가능한 변수를 관리하는 것이 가능
useRef
로 관리하는 변수는 값이 바뀌어도 리렌더링 X
→ 리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출한 뒤에야 업데이트된 상태를 조회가능
→ useRef
로 관리하는 변수는 설정 후 바로 조회가능
setTimeout
, setInterval
을 통해서 만들어진 id
const nextId = useRef(4);
const onCreate = () => {
// 나중에 구현 할 배열에 항목 추가하는 로직
nextId.current += 1;
};
useRef()
의 파라미터 : .current
의 기본값. .current
를 수정해서 해당 변수값을 조작한다.
불변성을 지켜야 한다!
→ push
, splice
, sort
등의 함수 사용금지
...
spread 연산자 사용const [users, setUsers] = useState([
{
id: 1,
username: 'velopert'
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username
};
setUsers([...users, user]);
nextId.current += 1;
};
concat
함수 사용const [users, setUsers] = useState([
{
id: 1,
username: 'velopert'
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username
};
setUsers(users.concat(user));
nextId.current += 1;
};
불변성을 지켜야 한다!
→ filter
함수 추천 → 특정 조건만 만족하는 새로운 배열을 만들기 때문
const onRemove = id => {
// user.id 가 불일치하는 원소만 추출해서 새로운 배열을 만듬
// 결과적으로, user.id === id 인 것을 제거
setUsers(users.filter(user => user.id !== id));
};
불변성을 지켜야 한다!
→ map
함수 사용하여 수정할 항목을 특정하고, 값을 변경 → 수정사항이 적용된 새로운 배열이 탄생 → 새로운 배열로 상태 교체
const onToggle = id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
특정 상황에서의 작업 처리
props
로 받은 값을 컴포넌트의 로컬 상태로 설정setInterval
(반복작업), setTimeout
(작업예약)setInterval
, setTimeout
으로 등록한 작업 clearclearInterval
, clearTimeout
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
useEffect(paramA, paramB)
paramA
: 함수cleanup
함수useEffect
에서 반환하는 함수useEffect
의 뒷정리를 함deps
가 비어있을 때 호출됨paramB
: 의존값이 들어있는 배열 deps
→ 생략시 컴포넌트가 처음 나타날 때에만 useEffect
에 등록한 함수가 호출됨deps
배열에 특정값이 있다면!
useEffect
내부에서 사용하는 상태, props는 deps
에 반드시 추가한다.
(?) 추가하지 않을 시
→ useEffect
에 등록한 함수가 실행될 때 최신 상태, props를 반영 X
연산된 값을 재사용하여 성능 최적화를 돕는 기능
useMemo(paramA, paramB)
paramA
: 함수. 어떻게 연산할 지.paramB
: deps
배열.특정 함수를 재사용
→ props
가 변경되지 않으면 Virtual DOM이 새로 렌더링되지 않게 최적화하는 과정에 필요한 기능
const [users, setUsers] = useState([
{
id: 1,
username: 'velopert',
email: 'public.velopert@gmail.com',
active: true
}
]);
const onToggle = useCallback(
id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
},
[users]
);
useEffect
내부에서 사용하는 상태, props는 deps
에 반드시 추가한다.
(?) 추가하지 않을 시
→ useEffect
에 등록한 함수가 실행될 때 최신 상태, props를 반영 X
→ useMemo
와 비슷하다. 기원이 useMemo
라서...
컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링을 하도록 설정가능
사용법: 필요한 부분을 React.memo()
로 감싸기
→ 다른 컴포넌트와 공통된 값을 deps
에서 공유하고 있다면, 연쇄적으로 리렌더링 됨
→ 공통 deps
제거 및 함수형 업데이트
ex) setUsers(users.concat(user))
→ setUsers(users => users.concat(user))
useState
처럼 상태를 관리하는 기능
VS useState
const [state, dispatch] = useReducer(reducer, initialState);
dispatch({type: "액션"})
useReducer
가 더 편할 수 있다