const [변수명, set함수명] = setState(초기값)
useEffect(이펙트 함수, 의존성 배열)
useEffect(이펙트 함수, [])
: 빈 배열. Effect function이 mount, unmont 시 단 한 번만 실행useEffect(이펙트 함수)
: 의존성 배열 생략 시 컴포넌트가 업데이트 될 때마다 호출 됨useEffect(() => {
// 컴포넌트가 마운트 된 이후,
// 의존성 배열에 있는 변수들 중 하나라도 값이 변경되었을 때 실행됨
// 의존성 배열에 빈 배열([])을 넣으면 마운트와 언마운트시에 단 한 번씩만 실행됨
// 의존성 배열 생략 시 컴포넌트 업데이트 시마다 실행됨
// class component의 componentDidMount, componentDidUpdate와 비슷하게 작동.
...
return () => {
// 컴포넌트가 마운트 해제되기 전에 실행됨
// class component의 componentDidUnmount와 비슷하게 작동.
...
}
}, [의존성 변수1, 의존성 변수2, ...]);
연산량이 많은
함수의 호출 결과를 저장
해뒀다가 같은 함수를 사용할 때 새로 함수를 호출하지 않고 이전에 저장해뒀던 값
을 사용const memoizedValue = useMemo(
() => {
// 연산량이 높은 작업을 수행하여 결과를 반환
return computeExpensiveValue(의존성 변수1, 의존성 변수2);
},
[의존성 변수1, 의존성 변수2]
);
함수
를 반환const memoizeddCallback = useCallback(
() => {
doSomething(의존성 변수1, 의존성 변수2);
},
[의존성 변수1, 의존성 변수2]
);
const refContainer = useRef(초기값);
Hook은 무조건 최상위 레벨
에서만 호출해야 한다.
리액트 함수 컴포넌트에서만
Hook을 호출해야 한다.
function MyComponent(props) {
const [name, setName] = useState('jihoh);
if (name !== '') {
useEffect(() => {
...
});
}
}
use로 시작
하고 내부에서 다른 Hook을 호출하는 하나의 자바스크립트 함수.// useCounter.jsx
import React, { useState } from "react";
function useCounter(initialValue) {
const [count, 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;
// Accommodate.jsx
import React, { useState, useEffect } from "react";
import useCounter from "./useCounter";
const MAX_CAPACITY = 10;
function Accommodate(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 onClick={decreaseCount}>퇴장</button>
{isFull && <p style={{ color: "red" }}>정원이 가득찼습니다.</p>}
</div>
);
}
export default Accommodate;
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Library from './chapter_03/Library';
import Clock from './chapter_04/Clock';
import CommentList from './chapter_05/CommentList';
import NotificationList from './chapter_06/NotificationList';
import Accommodate from './chapter_07/Accommodate';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Accommodate />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
// bind 사용해야 하는 예
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// callback에서 'this'를 사용하기 위해선 바인딩 필수
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? '켜짐' : '꺼짐'}
</button>
);
}
}
// class fields syntax 사용
class MyButton extends React.Component {
// class fields
handleClick = () => {
console.log('this is:', this);
}
rendef() {
return (
<button onClick={this.handleClick}>
클릭
</button>
);
}
}
// 이벤트 핸들러에 arrow function을 넣는 방식
class MyButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 이렇게 하면 'this'가 바운드됩니다.
// 마이버튼 컴포넌트가 렌더링 될 때마다 다른 콜백함수가 생성된다는 문제가 있음
// 이 콜백 함수가 하위 컴포넌트의 props으로 넘겨지게 되면 하위 컴포넌트에서 추가적인 렌더링이 발생
// 성능 문제를 피하기 위해선 binding이나 class fields syntax를 사용하는 게 좋음
return (
<button onClick={() => this.handleClick()}>
클릭
</button>
);
}
}
function Toggle(props) {
const [isToggleOn, setIsToggleOn] = useState(true);
// 방법 1. 함수 안에 함수로 정의
function handleClick() {
setIsToggleOn((isToggleOn) => !isToggleOn);
}
// 방법 2. arrow function을 사용하여 정의
const handleClick = () => {
setIsToggleOn((isToggleOn) => !isToggleOn);
}
return (
// 함수 컴포넌트는 이벤트를 넣어줄 때 this를 사용하지 않고 곧바로 정의한 이벤트 핸들러를 전달하면 됨
<button onClick={handleClick}>
{isToggleOn ? "켜짐" : "꺼짐"}
</button>
);
// 1. arrow function 사용
// 명시적으로 react의 event 객체를 두 번째 매개변수로 전달
<button onClick={(event) => this.deleteItem(id, event)}>삭제하기</button>
// 2. bind 사용
// 리액트가 알아서 event를 id 이후의 매개변수로 전달
<button onClick={this.deleteItem.bind(this, id)}>삭제하기</button>
function MyButton(props) {
const handleDelete = (id, event) => {
console.log(id, event.target);
};
return (
<button onClick={(event) => handleDelete(1, event)}>
삭제하기
</button>
);
}
import React from "react";
class ConfirmButton extends React.Component {
constructor(props) {
super(props);
this.state = {
isConfirmed: false,
}
this.handleConfirm = this.handleConfirm.bind(this);
};
handleConfirm() {
this.setState((prevState) => ({
isConfirmed: !prevState.isConfirmed,
}));
}
render() {
return (
<button
onClick={this.handleConfirm}
disabled={this.state.isConfirmed}
>
{this.state.isConfirmed ? "확인됨" : "확인하기"}
</button>
);
}
}
export default ConfirmButton;
import React from "react";
class ConfirmButton extends React.Component {
constructor(props) {
super(props);
this.state = {
isConfirmed: false,
};
}
handleConfirm = () => {
this.setState((prevState) => ({
isConfirmed: !prevState.isConfirmed,
}));
}
render() {
return (
<button
onClick={this.handleConfirm}
disabled={this.state.isConfirmed}
>
{this.state.isConfirmed ? "확인됨" : "확인하기"}
</button>
);
}
}
export default ConfirmButton;
import React, { useState } from "react";
function ConfirmButton(props) {
const [isConfirmed, setIsConfirmed] = useState(false);
const handleConfirm = () => {
setIsConfirmed((prevIsConfirmed) => !prevIsConfirmed);
};
return (
<button onClick={handleConfirm} disable={isConfirmed}>
{isConfirmed ? "확인됨" : "확인하기"}
</button>
);
}
export default ConfirmButton;
![]() | ![]() |
---|