- 함수형 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를 사용한다.