서로 비슷한 것을 하는 작은 함수의 묶음으로 사용 가능
함수 컴포넌트에서 React state와 생명주기 기능을 연동(hook into)할 수 있게 해주는 함수
함수 컴포넌트 내에서 side effects를 수행할 수 있도록 도와준다
useEffect = componentDidMount, componentDidUpdate, componentWillUnmount
ex) useEffect(() => { doc.title = hi ${user.id}
}
useEffect를 사용하면, React는 DOM을 바꾼 뒤에 'effect'함수를 실행한다
Effects는 컴포넌트 안에 선언되어 있기 때문에 props와 state에 접근 가능하다.
기본적으로 React는 매 렌더링 이후에 effects를 실행한다(첫번재 렌더링 포함)
만약 effect를 해제할 필요가 있다면? 해제하는 함수는 반환 (optional)
useEffect (() => {
// Rerender Component
console.log('dooing something');
return () => {
// Unmount Component
console.log('effect done');
}
}
=> useContext를 호출한 컴포넌트는 context값이 변경되면 항상 리렌더링 된다.
- 만약 많은 리렌더링이 필요하다면? 메모이제이션 사용
useState의 대체 함수
1) const [state, dispatch] = useReducer(reducer, inintialArg, init);
2) const [state, dispatch] = useReducer(reducer, {count: initialArg});
(state, action => new State의 형태로 reducer를 받고 dispatch 메서드와 짝의 형태를 가진 현재 state를 반환한다.
이전 state에 의존적일 경우에 보통 useReducer를 더 선호한다.
=> 콜백 대신 dispatch를 전달할 수 있기 때문에
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
return init(action.payload);
default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
필요한 hook들을 정의해서 커스텀 훅을 만들 수 있다
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}