리액트는 상위 컴포넌트의 sate가 업데이트가 되면 그 하위 컴포넌트까지 제렌더링 된다.
함수가 다시 호출되고, 값을 다시 부른다는 뜻이다.
이렇게 되면 에너지 낭비이기 때문에 리액트에선 3가지 훅을 제공한다.
이 3가지 훅은 값이나 함수를 메모리에 저장해 자원을 아낄 수 있다.
useCallback(함수),useMemo(값),useReducer
각각 하나씩 살펴보겠다.
useCallback
두가지 인자를 받는다.
1.메모이제이션
2.의존성 배열
의존성 배열의 값이 변경되지 않는 한 , 동일한 함수 인스턴스를 반환한다.
사용방법
const 변수선언 = useCallback(()=>{},[])
const increment = useCallback(()->{
//이 함수 내부에서 발생하는 일이
//굉장히 비용이 많이 발생하는 코드가 정의되어 있으면 쓴다.
setCount(()=>prev + 1})
},[])
useCallback으로 메모이제이션 할 땐 ,
처음 세팅 그대로 저장한다.
그래서 계속해서 변하는 값을 참조 하고 싶으면 아래와 같이 쓰면 된다.
setCount(값) - 이전 값을 참조하지 않을 때.
setCount(()=>{}) - 이전 값을 참조할 때
useMemo
값의 메모이제이션을 위해 사용된다.
의존성배열에 있는 값이 안변하면 재계산 안함.(불필요한 계산 X , 성능 최적화 목표)
//기본 사용법
const 변수선언 = useMemo(()=>{},[의존성배열])
const memoizedValue = useMemo(() => {
// 계산할 값
return someExpensiveCalculation(a, b);
}, [a, b]); // 의존성 배열
import React, { useState, useMemo } from 'react';
function ExpensiveCalculationComponent() {
const [count, setCount] = useState(0);
const expensiveCalculation = (num) => {
console.log('Calculating...');
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
return (
<div>
<p>Count: {count}</p>
<p>Calculated Value: {memoizedValue}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default ExpensiveCalculationComponent;
useReducer
리액트에서 상태 관리를 위한 훅이다.
컴포넌트 로컬 상태를 관리할 때 주로 쓰는데, 폼데이터 같은 복잡한 데이터를 관리하는 데 유용하다.
const [state, dispatch] = useReducer(reducer, initialState);
import React, { useReducer } from 'react';
const initialState = {
name: '',
email: '',
password: ''
};
function reducer(state, action) {
switch (action.type) {
case 'setFieldValue':
return {
...state,
[action.field]: action.value
};
case 'reset':
return initialState;
default:
throw new Error('Unknown action type');
}
}
function RegistrationForm() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = (e) => {
dispatch({ type: 'setFieldValue', field: e.target.name, value: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(state);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Name:
<input
type="text"
name="name"
value={state.name}
onChange={handleChange}
/>
</label>
</div>
<div>
<label>
Email:
<input
type="email"
name="email"
value={state.email}
onChange={handleChange}
/>
</label>
</div>
<div>
<label>
Password:
<input
type="password"
name="password"
value={state.password}
onChange={handleChange}
/>
</label>
</div>
<button type="submit">Register</button>
<button type="button" onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</form>
);
}
export default RegistrationForm;
장점
1.복잡한 에러 처리 : 여러 상태와 액션을 다루는 로직을 깔끔하게 관리할 수 있다.
2.상태 로직 분리 : 상태 업데이트 로직을 컴포넌트에서 분리해 코드의 가독성과 유지보수성을 높힌다.
3.불변성 유지 : 새로운 상태를 변환하여 상태 불변성을 유지한다.
4.확장성 : 상태와 액션을 추가하기 쉽다.
다만,복잡성이 증가할 수 있고, 전역상태관리가 필요하면 , redux같은 걸 쓰는 게 좋다.
'Front-End > React' 카테고리의 다른 글
서버 띄우는법 , http통신 (0) | 2024.07.26 |
---|---|
Context API (0) | 2024.07.26 |
리액트 불변성 (0) | 2024.07.25 |
코드분석(To-do-list) (3) | 2024.07.24 |
조건부 렌더링 (0) | 2024.07.24 |