
함수 컴포넌트에서 React state의 생명 주기 기능을 '연동'할 수 있게 해주는 함수
class 대신 React를 사용할 수 있게 도와줌
- 최상위 에서만 Hook을 호출해야 함. 반복문, 조건문, 중첩된 함수 내에서는 불가 : React가 Hook이 호출되는 순서에 의존하므로, 호출 순서가 달라지게 된다면 버그를 발생시킴
- React 함수 컴포넌트 내에서만 Hook을 호출해야 함, 일반 JS함수에서는 불가능 (custom Hook) 제외
useState : state를 함수 컴포넌트 안에서 사용할 수 있게 해줌
import React, {useState} from 'react';
function Example() {
const [count, setCount] = useState(0);
setCount가 호출됨)var fruitStateVariable = useState('banana');
var fruit = fruitStateVariable[0];
var setFruit = fruitStateVariable[1];
this.state.count 대신 count를 직접 사용할 수 있음<p>You clicked {count} times</p>
setCount와 count 변수를 가지고 있으므로 this를 호출하지 않아도 됨<button onClick={() => setCount(count+1)}>
Click me!
</button>
side effects(컴포넌트 안에서 데이터를 가져오거나 구독하고 DOM을 직접 조작하는 작업과 같이 다른 컴포넌트에 영향을 주는 작업)를 수행할 수 있게 해줌 <b>useEffect</b> React class의componentDidMount,componentDidUpdate,componentWillUnmount`가 하나의 API로 통합된 것
useEffect를 사용하여 React에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야 하는 지를 알려줌 React는 우리가 넘긴 함수(
effect)를 기억했다가 DOM 업데이트를 수행한 이후 불러냄
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You cliked ${count} times`;
});
}
이때
useEffect안에 함수를 전달함 이때의 함수가effect
같은 함수 내부에 있기 때문에 최신의count를 바로 얻을 수 있음
리렌더링 때마다 이전과 다른 effect로 교체해서 전달
effect에서 함수를 반환한다면?
이는 effect를 위한 추가적인 정리(
clean-up) 메커니즘임
따라서 컴포넌트 마운트가 해제되는 때 정리를 실행함useEffect (()=> { function handleStatusChange(status){ setIsOnline(status.isOnline); } ChatAPI.subscriptToFriendStatus(props.friend.id, handleStatusChange); return() => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; });
상태 유지 값과 그 값을 갱신하는 함수를 반환
최초 렌더링 시, 반환된 state는 첫 번째 전달된 인자의 값과 같음
이전 state를 사용해서 새로운 state를 계산하는 경우 함수를
setState로 전달함
따라서 setState는 이전 값을 받아 갱신된 값을 반환
initalState 는 초기 렌더링 시에 사용하는 state으로 이후 렌더링 시 무시됨
예시로 살펴보자
function Counter({initalState}) {
const [count, setCount ] =useState(initalCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initalCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount -1)}> - </button>
);
}
명령형 또는 어떤 effect를 발생하는 함수를 인자로 받음
useEffect로 전달된 정리 함수는 UI에서 컴포넌트를 제거하기 전에 수행됨 (clean-up)
useEffect에 전달된 함수는 화면에 렌더링이 완료된 후(레이아웃 배치와 그리기를 완료한 후)에 수행됨
예시로 살펴보자
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
//Clean up the subscription
subscription.unsubscribe();
};
});
effect가 종속되어 있는 값의 배열인
useEffect의 두번째 인자를 전달하여, 해당 배열이 변경될 때 effect가 일어남, 이때 빈 배열을 전달하면 props나 state에서 가져온 어떤 값에도 의존하지 않으므로, 다시 실행할 필요가 전혀 없음
예시로 살펴보자
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
const value = useContext(MyContext);context 객체를 받아 context의 현재 값을 반환, 이때 context의 현재 값은 Hook을 호출하는 컴포넌트에 가장 가까이 있는
<MyContext.Provider>의valueprop에 의해 결정됨
이때,<MyContext.Provider>가 갱신되면 가장 최신의 context value를 사용하여 재랜더링을 시킴, 즉useContext를 구독하고 있는 컴포넌트 자체에서부터 재랜더링
예시로 살펴보자
const themes = {
light: {
foreground: '#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.lignt);
function App() {
return (
<ThemeContext.Provider value = {themes.dark}>
<Toolbar/>
</ThemeContext.Provider>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground}}>
I am styled by theme context!
</button>
);
}
const [state, dispatch] = useReducer(reducer, initalArg, init);
useState의 대체 함수로,
(state, action) => newState형태로 reducer를 받고dispatch메서드와 짝의 형태로 현재 state를 반환
다수의 하윗값을 포함하는 복잡한 정적 로직을 만드는 경우나 다음 state가 이전 state에 의존적인 경우 보통useReducer사용
initalArg: 초기 state를 두 번째 인자로 전달
init(initalArg): 초기 state 지연해서 생성
예시로 살펴보자
const init(initalCount) {
return {count:initalCount};
}
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({initalCount}) {
const [state, dispatch] = useReducer(reducer, initalCount, init);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'reset', payload: initalCount})}>Reset</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
const memoizedCallback = useCallback( () => { doSomething(a,b); }, [a,b], );메모이제이션된 콜백을 반환,
useCallback은 콜백의 메모이제이션된 버전을 반환함
메모이제이션된 버전은 콜백의 의존성이 변경되었을 때에만 변경됨
const memoizedValue = useMemo(() => computeExpensiveValue(a,b), [a,b]);메모이제이션된 값을 반환, 생성함수와 그것의 의존성 값의 배열을 전달
useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값을 다시 계산함
useMemo로 전달된 함수는 렌더링 중에 실행됨.
const refContainer = useRef(initalValue);
useRef는.current프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환함
useRef는.current프로퍼티에 변경 가능한 값을 담고있는 '상자' 와 같음
useRef는 매번 렌더링할 때 동안 동일한 ref 객체를 제공
예시로 살펴보자
function TextInputWithFocusButton() {
const inputE1 = useRef(null);
const onButtonClick = () => {
inputE1.current.focus();
};
return (
<>
<input ref={inputE1} type='text'/>
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}