일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- BFS
- 정렬
- 그리디
- 퀵정렬
- pytorch
- 알고리즘
- 재귀함수
- 최단 경로
- 삽입정렬
- RESNET
- 큐
- 다이나믹 프로그래밍
- Machine Learning
- DFS
- LSTM
- AI
- 이진 탐색
- 캐치카페신촌점 #캐치카페 #카페대관 #대학생 #진학사 #취준생
- GRU
- 머신러닝
- 계수정렬
- 스택
- 선택정렬
- 인공지능
- 딥러닝
- rnn
- 선형대수
- Today
- Total
hyeonzzz's Tech Blog
[리액트를 다루는 기술] 8장 Hooks 본문
8장 Hooks
Hooks
: useState, useEffect 등의 기능을 제공하여 다양한 작업을 할 수 있게 해준다
8.1 useState
● useState
: 함수 컴포넌트에서 상태를 관리해야 할 때 사용
● useState 사용해서 숫자 카운터 구현해보기
1. src 디렉터리에 Counter.js 파일 생성
//Counter.js
import React from 'react';
import { useState } from 'react';
const Counter = () => {
const [value, setValue] = useState(0);
/*카운터의 기본값을 0으로 설정한다
이 함수가 호출되면 배열을 반환한다
배열의 첫 번째 원소는 상태 값, 두 번째 원소는 상태를 설정하는 함수이다*/
return (
<div>
<p>
현재 카운터 값은 <b>{value}</b>입니다.
</p>
<button onClick={() => setValue(value + 1)}>+1</button>
<button onClick={() => setValue(value - 1)}>-1</button>
</div>
);
};
export default Counter;
2. App 컴포넌트에서 Counter 컴포넌트 렌더링
//App.js
import React from "react";
import Counter from "./Counter";
const App = () => {
return <Counter />;
};
export default App;
3. 터미널에 yarn start 명령어 입력해 개발 서버 구동
● useState를 여러 번 사용하기
1. Info.js 파일 생성
//Info.js
import React from 'react';
import { useState } from 'react';
const Info = () => {
const [name, setName] = useState('');
const [nickname, setNickname] = useState('');
const onChangeName = e => {
setName(e.target.value);
};
const onChangeNickname = e => {
setNickname(e.target.value);
};
return (
<div>
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickname} />
</div>
<div>
<div>
<b>이름:</b> {name}
</div>
<div>
<b>닉네임:</b> {nickname}
</div>
</div>
</div>
);
};
export default Info;
2. App 컴포넌트에서 렌더링
//App.js
import React from "react";
import Info from "./Info";
const App = () => {
return <Info />;
};
export default App;
3. 화면 확인
8.2 useEffect
● useEffect
: 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook
● Info 컴포넌트에 useEffect 적용
//Info.js
import React from 'react';
import { useState, useEffect } from 'react';
const Info = () => {
const [name, setName] = useState('');
const [nickname, setNickname] = useState('');
useEffect(() => {
console.log('렌더링이 완료되었습니다! ');
console.log({
name,
nickname
});
});
const onChangeName = e => {
setName(e.target.value);
};
const onChangeNickname = e => {
setNickname(e.target.value);
};
/*
return (
<div>
<div>
<input value={name} onChange={onChangeName} />
<input value={nickname} onChange={onChangeNickname} />
</div>
<div>
<div>
<b>이름:</b> {name}
</div>
<div>
<b>닉네임:</b> {nickname}
</div>
</div>
</div>
);
};
*/
export default Info;
※ 컴포넌트가 화면에 나타날 때 두 번 호출이 된다
● 마운트될 때만 실행하고 싶을 때
//Info.js
useEffect(() => {
console.log('마운트될 때만 실행됩니다.');
}, []);
컴포넌트가 처음 나타날 때만 콘솔에 문구가 나타나고, 이후에는 나타나지 않는다
● 특정 값이 업데이트될 때만 실행하고 싶을 때
//Info.js
useEffect(() => {
console.log(name);
}, [name]);
useEffect의 두번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값을 넣어 준다
● 뒷정리하기
1. Info 컴포넌트의 useEffect 부분 수정
//Info.js
useEffect(() => {
console.log('effect');
console.log(name);
return () => {
console.log('cleanup');
console.log(name);
};
}, [name]);
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떠한 작업을 수행하고 싶다면
useEffect에서 cleanup 함수를 반환해준다
2. App 컴포넌트에서 Info 컴포넌트의 가시성을 바꿀 수 있게 수정
//App.js
import React from "react";
import { useState } from "react";
import Info from "./Info";
const App = () => {
const [visible, setVisible] = useState(false);
return (
<div>
<button
onClick={() => {
setVisible(!visible);
}}
>
{visible ? '숨기기' : '보이기'}
</button>
<hr />
{visible && <Info />}
</div>
);
};
export default App;
렌더링될 때마다 뒷정리 함수가 계속 나타난다
뒷정리 함수가 호출될 때는 업데이트되기 직전의 값을 보여준다
8.3 useReducer
● useReducer
: useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해주고 싶을 때 사용하는 Hook
● 카운터 구현하기
state : 현재 가리키고 있는 상태
dispatch : 액션을 발생시키는 함수
● 인풋 상태 관리하기
useReducer에서의 액션을 어떤 값도 사용 가능
8.4 useMemo
● useMemo
: 함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있다
● 리스트에 숫자를 추가하면 평균을 보여주는 함수 컴포넌트
1. src 디렉터리에 Average.js 파일 생성
import React from "react";
import { useState } from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중..');
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 onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
2. App에서 컴포넌트 렌더링
//App.js
import React from "react";
import Average from "./Average";
const App = () => {
return <Average />;
};
export default App;
3. useMemo Hook 사용
import React from "react";
import { useState, useMemo } from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중..');
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 onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
const avg = useMemo(() => getAverage(list), [list]); //useMemo 사용
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
인풋 내용이 바뀔 때는 평균값이 다시 계산되지 않는다
8.5 useCallback
● useCallback
: 렌더링 성능을 최적화해야 하는 상황에서 사용한다
만들어 놨던 함수를 재사용할 수 있다
● useCallback 사용하여 최적화하기
import React from "react";
import { useState, useMemo, useCallback } from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중..');
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 onChange = useCallback(e => {
setNumber(e.target.value);
}, []); // 컴포넌트가 처음 렌더링될 때만 함수 생성
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
}, [number, list]); // number 혹은 list가 바뀌었을 때만 함수 생성
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
useCallback의
- 첫 번째 파라미터 : 생성하고 싶은 함수
- 두 번째 파라미터 : 배열
8.6 useRef
● useRef
: 함수 컴포넌트에서 ref를 쉽게 사용할 수 있도록 해주는 Hook
import React from "react";
import { useState, useMemo, useCallback, useRef} from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중..');
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 inputE1 = useRef(null);
const onChange = useCallback(e => {
setNumber(e.target.value);
}, []); // 컴포넌트가 처음 렌더링될 때만 함수 생성
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
inputE1.current.focus();
}, [number, list]); // number 혹은 list가 바뀌었을 때만 함수 생성
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} ref={inputE1} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {avg}
</div>
</div>
);
};
export default Average;
'React' 카테고리의 다른 글
[리액트를 다루는 기술] 15장 Context API (0) | 2023.02.10 |
---|---|
[리액트를 다루는 기술] 9장 컴포넌트 스타일링 (0) | 2023.01.27 |
[리액트를 다루는 기술] 7장 컴포넌트의 라이프사이클 메서드 (0) | 2023.01.27 |
[리액트를 다루는 기술] 3장 컴포넌트 (0) | 2023.01.16 |