- 함수형 Component는 jsx를 반환한다.
- Component가 렌더링 된다는 것은 해당 Component를 호출했다는 것, 그렇다면 기본적으로 선언된 변수나 함수는 초기화된다.
- Component에서 State 값이 변경되면, 해당 Component(부모)와 하위 Component(자식)는 재 렌더링 된다.
렌더링에 영향을 받는 것이 2번째 매개변수의 변화에만 영향을 받아 처리
useCallback(fn, deps)은 useMemo(() => fn, deps)와 같습니다.
사용이유는 어떤 컴포넌트 렌더링에 영향을 받아 매번 같은 결과를 반환하는 부분을 처리하는 것을 막기 위해서 (ex 심각한 counting 여러번 하는 것까지 )
import react, { useState, useMemo, useCallback } from "react";
import User from './components/Box/index.js'
export default function App() {
console.log("부모!");
const [name, setName] = useState("");
const [age, setAge] = useState("");
//기존 유저 이름 변경 함수
const onChangeName = (e) => {
const data = e.target.value;
console.log("data : ", data);
setName(data);
};
//기존 유저 이름 변경 함수
const onChangeAge = (e) => {
const age = e.target.value;
console.log("age : ", age);
setAge(age);
};
return (
<div className="App">
<h1>부모 컴포넌트</h1>
<User
name={name}
age={age}
onChangeName={onChangeName}
onChangeAge={onChangeAge}
/>
</div>
);
}
import react, { useMemo, useCallback } from "react";
const setNameTag = (name) => {
console.log("이름 태그!!!!!!!!!!!!!!!!!!!!!!!");
return `이름은 : ${name}`;
};
const setAgeTag = (name) => {
console.log("나이 태그~~~");
return `나이는 : ${name}`;
};
const User = (props) => {
console.log("자식");
//일반적인 props 받은 값
const nameFunc =setNameTag(props.name)
const ageFunc =setAgeTag(props.age)
const naem = useMemo(()=>nameFunc, [props.name]);
const age = useMemo(()=>ageFunc, [props.age]);
// const nameFunc =setNameTag(props.name)
// const ageFunc =setAgeTag(props.age)
// const naem = useCallback(nameFunc, [props.name]);
// const age = useCallback(ageFunc, [props.age]);
return (
<div>
<h1>{naem}</h1>
<h1>{age}</h1>
<div>
<input type="text" onChange={(e) => props.onChangeName(e)} />
</div>
<div>
<input type="text" onChange={(e) => props.onChangeAge(e)} />
</div>
</div>
);
};
export default User
import react, { useState, useMemo, useCallback } from "react";
import User from './components/Box/index.js'
export default function App() {
console.log("부모!");
const [name, setName] = useState("");
const [age, setAge] = useState("");
//기존 유저 이름 변경 함수
const onChangeName = (e) => {
const data = e.target.value;
console.log("data : ", data);
setName(data);
};
//기존 유저 이름 변경 함수
const onChangeAge = (e) => {
const age = e.target.value;
console.log("age : ", age);
setAge(age);
};
return (
<div className="App">
<h1>부모 컴포넌트</h1>
<User
name={name}
age={age}
onChangeName={onChangeName}
onChangeAge={onChangeAge}
/>
</div>
);
}
import react, { useMemo, useCallback } from "react";
const setNameTag = (name) => {
console.log("이름 태그!!!!!!!!!!!!!!!!!!!!!!!");
return `이름은 : ${name}`;
};
const setAgeTag = (name) => {
console.log("나이 태그~~~");
return `나이는 : ${name}`;
};
const User = (props) => {
console.log("자식");
//일반적인 props 받은 값
// const nameFunc =setNameTag(props.name)
// const ageFunc =setAgeTag(props.age)
// const naem = useMemo(()=>nameFunc, [props.name]);
// const age = useMemo(()=>ageFunc, [props.age]);
//
const nameFunc =setNameTag(props.name)
const ageFunc =setAgeTag(props.age)
const naem = useCallback(nameFunc, [props.name]);
const age = useCallback(ageFunc, [props.age]);
return (
<div>
<h1>{naem}</h1>
<h1>{age}</h1>
<div>
<input type="text" onChange={(e) => props.onChangeName(e)} />
</div>
<div>
<input type="text" onChange={(e) => props.onChangeAge(e)} />
</div>
</div>
);
};
export default User
두 차이는 useMemo에서는
useMemo(()=>nameFunc, [props.name]);
를 사용하여 return된 값이 이용되고
useCallback에서는useCallback(nameFunc, [props.name]);
콜백 함수로 매개변수가 이용된다.
함수가 재정의 되면서 새로운 메모리를 할당될 함수가 어떤 이벤트로 넘어가면 새롭게 정의되어 이는 React.memo로 막을 수 없는 부분으로 useCallback이 담당해야한다.
import react, { useState, useMemo, useCallback } from "react";
import User from './components/Box/index.js'
export default function App() {
console.log("부모!");
const [count , setCount] = useState(0);
const [name, setName] = useState("");
const [age, setAge] = useState("");
return (
<div className="App">
<button onClick={()=>setCount(count+1)}>+</button>
<h1>부모 컴포넌트</h1>
<User/>
</div>
);
}
import react, { useMemo, useCallback } from "react";
import React from "react"
const User = ((props) => {
console.log("자식");
return (
<div>
<h1>{props.name}</h1>
<h1>{props.age}</h1>
<div>
<input type="text" onChange={(e) => props.onChangeName(e)} />
</div>
<div>
<input type="text" onChange={(e) => props.onChangeAge(e)} />
</div>
</div>
);
});
export default User
버튼을 누르면 결과는
부모 자식
전부 출력된다.
즉, 버튼과 상관없는 컴포넌트의 자식태그가 영향을 받아 자식을 출력한다.
React.memo
로 index.js의 const User를 묶으면
버튼을 누르면부모
만 출력된다.
즉, 다른 부모 컴포넌트에 영향을 받지않는 자식 컴포넌트가 된다.
import react, { useState, useMemo, useCallback } from "react";
import User from './components/Box/index.js'
export default function App() {
console.log("부모!");
const [count , setCount] = useState(0);
const [name, setName] = useState("");
const [age, setAge] = useState("");
//기존 유저 이름 변경 함수
const onChangeName = useCallback((e) => {
const data = e.target.value;
console.log("data : ", data);
setName(data);
},[]);
//기존 유저 이름 변경 함수
const onChangeAge = useCallback((e) => {
const age = e.target.value;
console.log("age : ", age);
setAge(age);
});
return (
<div className="App">
<button onClick={()=>setCount(count+1)}>+</button>
<h1>부모 컴포넌트</h1>
<User
onChangeAge={onChangeAge}
onChangeName={onChangeName}
/>
</div>
);
}
부모 컴포넌트에 onChangeAge와 onChangeName 이벤트가 있는 와중에
React.memo는 유지한 상태로 버튼을 누르면부모 자식
전부 출력된다.
원인 : 함수(컴포넌트)가 재정의 되면서 새로운 메모리 할당될 함수가 onchange로 넘어와서 이를 통해 다시 User 컴포넌트가 렌더링이 된다.
- useCallback은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용
- 즉, 특정함수가 만들어지지 않으므로 컴포넌트가 따로 렌더링 되지않는다.
import react, { useState, useMemo, useCallback } from "react";
import User from './components/Box/index.js'
export default function App() {
console.log("부모!");
const [count , setCount] = useState(0);
const [name, setName] = useState("");
const [age, setAge] = useState("");
//기존 유저 이름 변경 함수
const onChangeName = useCallback((e) => {
const data = e.target.value;
console.log("data : ", data);
setName(data);
},[]);
//기존 유저 이름 변경 함수
const onChangeAge = useCallback((e) => {
const age = e.target.value;
console.log("age : ", age);
setAge(age);
},[]);
return (
<div className="App">
<button onClick={()=>setCount(count+1)}>+</button>
<h1>부모 컴포넌트</h1>
<User
onChangeAge={onChangeAge}
onChangeName={onChangeName}
/>
</div>
);
}
해당 원인이었던 onChangeAge와 onChangeName을 useCallback을 이용하여
버튼을 눌렀을때에도부모
만 출력된다.
- 부모 state가 변경되어도 자식 컴포넌트에 영향을 준다.
- 그것을 막기 위해서 자식 컴포넌트를
React.memo
로 묶어서 영향을 막는다- 하지만 해당 컴포넌트에 이벤트가 걸려져 있다면 함수가 재정의 되면서 새로운 메모리가 할당되고 이는 다시 영향을 준다.
- 이것을 막기 위해
useCallback
을 사용하여 특정 함수를 새로 만들지 않고 재사용하므로 영향을 막는다.- 그외에도 계산을 길게하는 함수를 통한 리턴 값을 매번 영향을 받는다고 동작시키는 것을 막기 위해 성능 최적화를 위하여 연산된 값을 가지는
useMemo
를 사용한다.