클래스형 컴포넌트의 componentDidMount와 compontDidUpdate를 합친 형태
//...
useEffect(() => {
console.log('rendering complete');
console.log({ number });
},[]); // 마운트될 때만 실행하고 업데이트 될때는 실행하지 않고 싶을때
//...
useEffect에서 설정한 함수를 컴포넌트가 화면에 맨 처음 렌더링될 때만 실행하고, 업데이트 될때는 실해하지 않으려면 함수의 두번째 파라미터로 비어있는 배열을 넣어준다
//...
const [number, setNumber] = useState(0);
//...
useEffect(() => {
console.log('rendering complete');
console.log({ number });
},[number]); //특정 값이 업데이트 될 때만 실행하고 싶을 때
//...
특정 값이 업데이트 될 때만 useEffect를 실행하고 싶을 때는 두번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값을 넣어준다.
//...
useEffect(() => {
console.log('rendering complete');
console.log({ number });
return () => { // 컴포넌트가 언마운트 되기전이나 업데이트되기 직전에
console.log('cleanup'); // 어떤 작업을 수행하고 싶으면 해당 작업을 수행하는
}; // cleanup 함수를 return
});
//...
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떠한 작업을 수행하고 싶을 때는 useEffect에서 cleanup함수를 return 한다
//...
useEffect(() => {
console.log('rendering complete');
console.log({ number });
return () => {
console.log('cleanup');
};
}, []); //언마운트될 때만 cleanup 함수를 호출하고 싶은 경우
//...
언마운트될 때만 cleanup함수를 호출하고 싶은 경우 두번째 파라미터로 빈 배열을 전달
useReducer
import React, { useReducer } from 'react';
// reducer 함수
function reducer(state, action) {
//action.type에 따라 다른 작업 수행
switch (action.type) {
case 'INCRESE':
return { number: state.number + 1 };
case 'DECRESE':
return { number: state.number - 1 };
default:
return { number: state.number };
}
} // 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼냄
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { number: 0 });
return (
<>
<hr />
<h1>{state.number}</h1>
<button onClick={() => dispatch({ type: 'INCRESE' })}>+1</button>
<button onClick={() => dispatch({ type: 'DECRESE' })}>-1</button>
<hr />
</>
);
};
export default Counter;
useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 관리할때 사용하는 hook
useReducer는 첫번째 파라미터로 reducer함수를, 두번째 파라미터로는 해당 리듀서의 기본값을 전달받는다.
reducer는 state(현재상태)와 action(상태 업데이트를 위한 정보)를 전달받아 새로운 상태를 반환하는 함수, 이때 반환되는 새로운 상태는 반드시 불변성을 지켜야 한다
useReducer는 state값과 dispatch함수를 return
state : 현재 가리키고 있는 상태
dispatch : 액션을 발생시키는 함수, dispacth(action)형태로 사용시 해당 action을 파라미터로 받은 reducer함수를 호출
useReducer의 장점은컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼수 있다는 점
useMemo
import React, { useState, useMemo } from 'react';
const getAverage = numbers => {
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const handleChange = e => {
setNumber(e.target.value);
};
const handleInsert = e => {
const newList = list.concat(parseInt(number));
setList(newList);
setNumber('');
};
// input의 value가 바뀌는 동안에는 평균값을 계산할 필요가 없으므로
// list 값이 바뀌었을 때만 연산일 실행하도록 한다
const avg = useMemo(() => getAverage(list), [list]);
return (
<>
<input value={number} onChange={handleChange} />
<button onClick={handleInsert}>등록</button>
<ul>
{list.map((value, index) => {
return <li key={index}>{value}</li>;
})}
</ul>
<p> avg : {avg}</p>
<hr />
</>
);
};
export default Average;
메모이제이션된 값을 반환함으로써 useMemo를 사용하면 함수형 컴포넌트 내부에서 발생하는 연산을 최적화
렌더링하는 과정에서 특정 값이 바뀌었을 때만 연산을 실행하고, 원하는 값이 바뀌지 않은경우 이전에 연산했던 결과를 다시 사용하는 방식
첫번째 파라미터로 생성함수를 전달하고, 두번째 파라미터로 의존성 값의 배열을 전달
useCallback
// ...
// const handleChange = e => {
// setNumber(e.target.value);
// };
const handleChange = useCallback(e => {
setNumber(e.target.value);
}, []); // 빈 배열 : 컴포넌트가 처음 렌더링될 때만 함수 생성
// const handleInsert = e => {
// const newList = list.concat(parseInt(number));
// setList(newList);
// setNumber('');
// };
const handleInsert = useCallback(
e => {
const newList = list.concat(parseInt(number));
setList(newList);
setNumber('');
},[number, list]); // number 또는 list가 변경될 때만 함수 생성
//...
메모이제이션된 콜백을 반환함으로써 불필요한 렌더링 방지
useCallback의 첫번째 파라미터에는 생성하고 싶은 함수를 넣고, 두번째 파라미터에는 배열을 넣는다. : 배열에는 어떤 값이 바뀌었을 때 함수를 생성해야하는지 명시
숫자, 문자열, 객체 처럼 일반 값을 재사용할 때는 useMemo를 사용하고, 함수를 재사용하려면 useCallback을 사용