리액트 16.8 이전 버전에서는 함수형 컴포넌트에서는 상태를 관리할 수 없었음
16.8부터 Hooks라는 기능이 도입되면서 함수형 컴포넌트에서도 상태 관리 가능
컴포넌트에서 동적인 값= State
useState함수를 사용하여 컴포넌트에서 상태를 관리할 수 있음
const [number, setNumber] = useState(0);
기존 값을 어떻게 업데이트 할 지에 대한 함수를 등록하는 방식으로도 값을 업데이트 할 수 있음
const onIncrease = () => {
setNumber(prevNumber => prevNumber + 1);
}
React에서 특정 DOM을 선택해야하는 상황에 ref 사용
함수형 컴포넌트에서 ref를 사용 할 때에는 useRef라는 Hook함수를 사용
const nameInput = useRef();
const onReset = () => {
setInputs({
name: '',
nickname: ''
});
nameInput.current.focus();
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
useRef는 DOM을 선택하는 용도 외에도 컴포넌트 안에서 조회 및 수정할 수 있는 변수를 관리하는 것
useRef로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 리렌더링되지
않음
리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회할 수 있는 반면, useRef로 관리하고 있는 변수는 설정 후 바로 조회할 수 있음
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
useEffect라는 Hook을 사용하여 컴포넌트가
특정 작업을 처리하는 방법
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
첫번째 파라미터에는 함수,
두번째 파라미터에는 의존값이 들어있는 배열 deps를 넣음
deps 배열을 비우게 되면 컴포넌트가 처음 나타날때에만 useEffect에 등록한 함수가 호출됨
useEffect 에서는 함수를 반환 할 수 있는데 이를 cleanup 함수라고 부름
cleanup 함수는 useEffect 에 대한 뒷정리
deps 가 비어있는 경우에는 컴포넌트가 사라질 때 cleanup 함수가 호출
deps에 특정값을 넣게 되면, 컴포넌트가 처음 mount/unmount 될 때에도 호출되고
지정한 값이 바뀔 때/바뀌기 직전에도 호출됨
useEffect(() => {
console.log('user 값이 설정됨');
console.log(user);
return () => {
console.log('user 가 바뀌기 전..');
console.log(user);
};
}, [user]);
useEffect 안에서 사용하는 상태나, props 가 있다면, useEffect 의 deps 에 넣어주어야 합니다. 그렇게 하는게, 규칙
만약 useEffect 안에서 사용하는 상태나 props 를 deps 에 넣지 않게 된다면 useEffect 에 등록한 함수가 실행 될 때 최신 props 상태를 가르키지 않게 됨
컴포넌트가 리렌더링 될 때마다 호출됨
참고로 리액트 컴포넌트는 기본적으로 부모컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링 됨(바뀐 내용 없어도)
성능 최적화를 위해 연산된 값을 useMemo라는 Hook을 사용하여 재사용
const count = useMemo(() => countActiveUsers(users), [users]);
useMemo를 사용하지 않으면 컴포넌트가 랜더링될 때(input 태그에 입력이 발생할 때)마다 countActiveUsers가 호출됨
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove} />
<div>활성사용자 수 : {count}</div>
</>
);
따라서 users에 변경이 생길 때에만 countActiveUsers가 호출 되도록 최적화하기 위해 useMemo 사용
첫번째 파라미터에는 어떻게 연산할지 정의하는 함수
두번째 파라미터에는 deps 배열
deps배열 안에 넣은 내용이 바뀌면 함수 호출해서 값을 연산
내용이 바뀌지 않았다면 이전에 연산한 값을 재사용
useCallback 은 useMemo 와 비슷한 Hook
useMemo는 특정 결과값(count)을 재사용 할 때 사용하는 반면,
useCallback은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용
한번 만든 함수를 필요할때만 새로 만들고 재사용하는 것은 중요
우리가 나중에 컴포넌트에서 props 가 바뀌지 않았으면 Virtual DOM 에 새로 렌더링하는 것 조차 하지 않고 컴포넌트의 결과물을 재사용 하는 최적화 작업을 할건데요, 이 작업을 하려면, 함수를 재사용하는것이 필수
함수 안에서 사용하는 상태 혹은 props 가 있다면 꼭, deps 배열안에 포함시켜야함
만약에 deps 배열 안에 함수에서 사용하는 값을 넣지 않게 된다면, 함수 내에서 해당 값들을 참조할때 가장 최신 값을 참조 할 것이라고 보장 할 수 없음
props 로 받아온 함수가 있다면, 이 또한 deps 에 넣어주어야함
useCallback, useMemo, Reacct.memo 는 컴포넌트의 성능을 실제로 개선할 수 있는 상황에서만 사용
현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태 반환
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
function Counter() {
const [number, dispatch] = useReducer(reducer, 0);
const onIncrease = () => {
dispatch({ type: 'INCREMENT' });
};
const onDecrease = () => {
dispatch({ type: 'DECREMENT' });
};
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
velopert와 함께하는 모던 리액트, https://react.vlpt.us/basic/17-useMemo.html [Accessed: June.28]