const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
import { useEffect, useState, useCallback } from "react";
import "./App.css";
function App() {
const [number, setNumber] = useState(0);
const someFunction = () => {
console.log(number);
};
useEffect(() => {
console.log("변경됨");
}, [someFunction]);
return (
<div className="App">
<input
type="number"
value={number}
onChange={(e) => {
setNumber(e.target.value);
}}
/>
<button onClick={someFunction}>Call someFunc</button>
</div>
);
}
export default App;
리액트 컴포넌트에서 state를 변경할 때 마다 컴포넌트는 다시 렌더링이 된다. 렌더링이 되면 함수 내부에 있는 모든 변수들은 다시 초기화가 되는데 someFunction도 하나의 변수이다. 이는 함수형태를 가지고 있는데 함수 역시 일종의 객체이다. 자바스크립트는 객체를 변수에 할당할때 객체가 변수안으로 바로 들어가진 않는다. 객체는 다른 메모리공간에 저장이 되고 메모리공간의 주소가 변수안에 들어가게 된다. 변수는 메모리 공간안에 있는 객체를 참조하고 있다. someFunction이라는 변수 안에는 객체가 들어있는 공간의 주소가 들어있다. 따라서 number이라는 state가 변경이 되어 렌더링이 되면 함수객체도 새로 생성이 되어 또다른 메모리 공간안에 저장이 된다. 이전과는 다른 메모리 주소가 들어가게 된다. 따라서 useEffect입장에서는 이전과 다른 주소값이 들어가 있는 someFunction은 다르다고 인식을 하고 콜백함수를 다시 호출한다.
import { useEffect, useState, useCallback } from "react";
import "./App.css";
function App() {
const [number, setNumber] = useState(0);
const someFunction = useCallback(() => {
console.log(number);
}, []);
useEffect(() => {
console.log("변경됨");
}, [someFunction]);
return (
<div className="App">
<input
type="number"
value={number}
onChange={(e) => {
setNumber(e.target.value);
}}
/>
<button onClick={someFunction}>Call someFunc</button>
</div>
);
}
export default App;
이를 해결하기 위해 useCallback을 사용한다.
처음 렌더링이 될때 someFunction이 만들어 지고 이는 메모이제이션이 되어 메모이제이션된 함수의 주소가 들어가 있게 된다. 그 다음 렌더링 부터는 someFunction함수는 더이상 새로 생성해서 만들어지는 것이 아니라 메모이제이션된 변수객체의 주소를 가지고 재사용한다.
하지만 여기서 문제는 버튼을 눌렀을 때 number은 바뀐 형태로 찍힌 것이 아닌 0으로 찍히게 된다. 이는 someFunction함수를 메모이제이션 해줬을때 number state는 0이었고 그 다음 렌더링 부터는 메모이제이제션 된 함수를 가져다 쓰므로 number에는 0이 계속 들어있다. 따라서 이를 해결하기 위해서는 두번째인자인 의존성배열안에 number을 넣어준다.
import { useEffect, useState, useCallback } from "react";
import "./App.css";
function App() {
const [number, setNumber] = useState(0);
const someFunction = useCallback(() => {
console.log(number);
}, [number]);
useEffect(() => {
console.log("변경됨");
}, [someFunction]);
return (
<div className="App">
<input
type="number"
value={number}
onChange={(e) => {
setNumber(e.target.value);
}}
/>
<button onClick={someFunction}>Call someFunc</button>
</div>
);
}
export default App;
'Front-end > React' 카테고리의 다른 글
| Custom hook (0) | 2022.03.14 |
|---|---|
| styled-components (0) | 2022.03.14 |
| [React] useMemo 원시타입/객체 타입 (0) | 2022.03.09 |
| Redux 란 ? Redux Setting Up - 1 (0) | 2022.03.07 |
| [React] Image Gallery 라이브러리 사용하기 (0) | 2022.02.23 |