728x90
반응형
Hooks의 개념과 useState, useEffect
Hook
갈고리
- 이름 앞에 use를 붙어야 함
useState
state를 사용하기 위한 Hook
import React, { useState } from "react"; function Counter(props) { var count = 0; return ( <div> <p>총 {count}번 클릭했습니다.</p> <button onClick={() => count++}> 클릭 </button> </div> ); }
useState() 사용법
const [변수명, set함수명] = useState(초기값);
import React, { useState } from "react"; function Counter(props) { const [count, setCount] = useState(0); // setCount : 변수 각각에 대해 set 함수가 따로 존재 return ( <div> <p>총 {count}번 클릭했습니다.</p> <button onClick={() => setCount(count + 1)}> 클릭 </button> </div> ); }
useEffect()
Side effect를 수행하기 위한 Hook
리액트에서 Side effect = 효과, 영향
- 일반적인 Side effect = 부작용
다른 컴포넌트에 영향을 미칠 수 있으며, 렌더링 중에는 작업이 완료될 수 없기 때문
리액트의 함수 컴포넌트에서 Side effect를 실행할 수 있게 해주는 Hook
useEffect() 사용법
useEffect(이펙트 함수, 의존성 배열);
Effect function이 mount, unmount 시에 단 한 번씩만 실행됨
useEffect(이펙트 함수, []);
의존성 배열을 생략하면 컴포넌트가 업데이트 될 때마다 호출됨
import React, { useState, useEffect } from "react"; function Counter(props) { const [count, setCount] = useState(0); // componentDidMount, componentDidUpdate와 비슷하게 작동합니다. useEffect(() => { // 브라우저 API를 사용해서 documnet의 title을 업데이트합니다. document.title = `You clicked ${count} times`; }); return ( <div> <p>총 {count}번 클릭했습니다.</p> <button onClick={() => setCount(count + 1)}> 클릭 </button> </div> ); }
import React, { useState, useEffect } from "react"; function UserStatus(props) { const [count, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.inOnline); } useEffect(() => { ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange); return () => { ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange); }; }); if (isOnline === null) { return '대기 중...'; } return isOnline ? '온라인' : '오프라인';
function UserStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `총 ${count}번 클릭했습니다.`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ServerAPI.subcribeUserStatus(props.user.id, handleStatusChange); return () => { ServerAPI.subcribeUserStatus(props.user.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ...
useEffect(() => { // 컴포넌트가 마운트 된 이후, // 의존성 배열에 있는 변수들 중 하나라도 값이 변경되었을 때 실해오딤 // 의존성 배열에 빈 배열([])을 넣으면 마운트와 언마운트시에 단 한 번씩만 실행됨 // 의존성 배열 생략 시 컴포넌트 업데이트 시마다 실행됨 ... return () => { // 컴포넌트가 마운트 해제되기 전에 실행됨 ... } }, [의존성 변수1, 의존성 변수2, ...]);
useMemo, useCallback, useRef
useMemo()
Memoized value를 리턴하는 Hook
Memoization : 연산량이 많이 드는 함수의 호출 결과를 저장해 두었다가, 같은 입력값으로 함수를 호출하면 새로 함수를 호출하지 않고, 이전에 저장해 두었던 호출 결과를 반환하는 것.
사용법
const memoizedValue = useMemo( () => { // 연산량이 높은 작업을 수행하여 결과를 반환 return computeExpensivaValue(의존성 변수1, 의존성 변수2); }, [의존성 변수1, 의존성 변수2] ); // 렌더링이 일어나는 동안 실행됨
의존성 배열을 넣지 않을 경우, 매 렌더링마다 함수가 실행됨
const memoizedValue = useMemo( () => computeExpensiveValue(a, b) );
의존성 배열이 빈 배열일 경우, 컴포넌트 마운트 시에만 호출됨
const memoizedValue = useMemo( () => { return computeExpensiveValue(a, b); }, [] );
useMemo, useCallback, useRef
useMemo() Hook과 유사하지만 값이 아닌 함수를 반환
사용법
const memoizedCallback = useCallback( () => { do Something(의존성 변수1, 의존성 변수2); }, [의존성 변수1, 의존성 변수2] ); // 의존성 배열의 값이 바뀐 경우에만 함수를 새로 정의해서 리턴 // 함수와 의존성 배열을 파라미터로 받음 // 파라미터로 받는 함수를 콜백이라고 부름 // 의존성 배열에 있는 변수 중 하나라도 바뀌면 메모이제이션된 콜백함수를 반환 // 의존성 배열에 따라 메모이즈드 된 값을 반환하는 것은 useMemo()와 동일
동일한 역할을 하는 두줄의 코드
useCallback(함수, 의존성 배열); useMemo(() => 함수, 의존성 배열);
import { useState } from "react"; function ParentComponent(props) { const |count, setCount| = useState(0); // 재렌더링 될 때마다 매번 함수가 새로 정의됨 const handleClick = (event) => { // 클릭 이벤트 처리 }; return ( <div> <button onClick={() => { setCount(count + 1); }} > {count} </button> <ChildComponent handleClick={handleClick} /> </div> ); }
import { useState } from "react"; function ParentComponent(props) { const |count, setCount| = useState(0); // 재렌더링 될 때마다 매번 함수가 새로 정의됨 const handleClick = (event) => { // 클릭 이벤트 처리 }; return ( <div> <button onClick={() => { setCount(count + 1); }} > {count} </button> <ChildComponent handleClick={handleClick} /> </div> ); }
=======
실습. Hooks 사용해보기
useCounter Hook 만들기
import React, { useState } from "react";
function useCounter(initialValue) {
const [const, setCount] = useState(initialValue);
const increaseCount = () => setCount((count) => count + 1);
const decreaseCount = () => setCount((count) => Math.max(count - 1, 0);
return [count, increaseCount, decreaseCount];
}
export default useCounter;
// useCounter Hook은 초기 카운트 값을 파라미터로 받아서,
// count라는 이름의 state를 생성하여 값을 제공하고,
// count 증가 및 감소를 편리하게 할 수 있도록 함수를 제공하는 Hook이다.
Accommodate 컴포넌트 만들기
import React, { useState, useEffect } from "react";
import useCounter from "./useCounter";
const MAX_CAPACITY = 10; // 최대 수용 인원
function Accomodate(props) {
const [isFull, setIsFull] = useState(false);
const [count, increaseCount, decreaseCount] = useCounter(0);
useEffect(() => {
console.log("================");
console.log("useEffect() is called.");
console.log(`isFull: ${isFull}`);
});
useEffect(() => {
setIsFull(count >= MAX_CAPACITY);
console.log(`Current count value: ${count}`);
}, {count});
return (
<div style={{ padding: 16 }}>
<p>{`총 ${count}명 수용했습니다.`}</p>
<button onClick={increaseCount} disabled={isFull}>
입장
</button>
<button Click={decreaseCount}>
퇴장
</button>
{isFull && <p style={{ color: "red" }}>정원이 가득찼습니다.</p>}
</div>
);
}
- 앞에서 만든 useCounter()를 사용하여 count를 관리한다.
- 두 개의 useEffect훅을 사용함 → 의존성 배열 유무
- 의존성 배열이 없는 형태는 컴포넌트가 마운트된 직후 호출, 이 후 컴포넌트가 업데이트 될 때마다 호출
- 의존성 배열이 있는 형태는 컴포넌트가 마운트된 직후 호출, 이 후 카운트 값이 바뀔 때마다 호출, 용량이 가득 찼는지 아닌지를 isFull에 저장
728x90
'개발 관련 학습 > React' 카테고리의 다른 글
[처음 만난 리액트] 섹션 9. Conditional Rendering (0) | 2023.03.13 |
---|---|
[처음 만난 리액트] 섹션 8. Handling Events (0) | 2023.03.12 |
[처음 만난 리액트] 섹션 6. State and Lifecycle (0) | 2023.03.10 |
[처음 만난 리액트] 섹션 5. Components and Props (0) | 2023.03.10 |
[처음 만난 리액트] 섹션 4. Rendering Elements (0) | 2023.03.10 |