๋ ๋๋ง ์ต์ ํ๋ฅผ ์ํ Hook, useMemo, useCallback
useMemo๋?
ํน์ ๊ฐ์ ์ฌ์ฌ์ฉํ๊ณ ์ ํ ๋ ์ฌ์ฉํ๋ Hook์ด๋ค.
์์ ์ฝ๋ ํด์
๐ props๋ก ๋์ด์จ value๊ฐ์ calculate๋ผ๋ ํจ์์ ์ธ์๋ก ๋๊ฒจ์ result ๊ฐ์ ๊ตฌํ ํ, <div> ์๋ฆฌ๋จผํธ๋ก ์ถ๋ ฅ์ ํ๊ณ ์๋ค.
function Calculator({value}){
const result = calculate(value);
return <>
<div>
{result}
</div>
</>;
}
๋ง์ฝ ์์ calculate๊ฐ ๋ด๋ถ์ ์ผ๋ก ๋ณต์กํ ์ฐ์ฐ์ ํด์ผ ํ๋ ํจ์๋ผ ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํํ๋ ๋ฐ์ ์๊ฐ์ด ๋ช ์ด ์ด์ ๊ฑธ๋ฆฐ๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด,
ํด๋น ์ปดํฌ๋ํธ๋ ๋ ๋๋ง์ ํ ๋๋ง๋ค ์ด ํจ์๋ฅผ ๊ณ์ํด์ ํธ์ถํ ๊ฒ์ด๊ณ , ๊ทธ ๋๋ง๋ค ์๊ฐ์ด ๋ช ์ด ์ด์ ์์๊ฐ ๋ ๊ฒ์ด๋ค.
์ ์ ์๊ฒ ์ข์ง ์์ UX๋ฅผ ์ฃผ๊ฒ ๋๋ค.
๐ ์ด๋ useMemo()๋ฅผ ์ฌ์ฉํด๋ณด์! ๐
/* useMemo๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์๋ ๊ผญ importํด์ ๋ถ๋ฌ์์ผ ํฉ๋๋ค. */
import { useMemo } from "react";
function Calculator({value}){
const result = useMemo(() => calculate(value), [value]);
return
<>
<div>
{result}
</div>
</>;
}
useMemo๋ฅผ ํธ์ถํ์ฌ calculate๋ฅผ ๊ฐ์ธ์ฃผ๋ฉด, ์ด์ ์ ๊ตฌ์ถ๋ ๋ ๋๋ง๊ณผ ์๋ก์ด ๊ตฌ์ถ๋๋ ๋ ๋๋ง์ ๋น๊ตํด value๊ฐ์ด ๋์ผํ ๊ฒฝ์ฐ์๋ ์ด์ ๋ ๋๋ง์ value๊ฐ์ ๊ทธ๋๋ก ์ฌํ์ฉํ ์ ์๊ฒ ๋๋ค. (๋ฉ๋ชจ์ด์ ์ด์ (Memoization) ๊ฐ๋ )
useMemo์ ํ์์ฑ
๊ฐ์ ์ปดํฌ๋ํธ ์์ ์๋ state์ค ํ๋๋ผ๋ ๋ณํ๊ฐ ์์ผ๋ฉด ๊ทธ ์ปดํฌ๋ํธ ์ ์ฒด๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋๋ฐ, ์ด๋ ๋ถํ์ํ๋ค!!
์ด๋ useMemo๋ฅผ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ํธ์ถ์ ์ค์ผ ์ ์๋ค! ๐
//App.js
import React, { useState } from "react";
import "./styles.css";
import { add } from "./add";
export default function App() {
const [name, setName] = useState("");
const [val1, setVal1] = useState(0);
const [val2, setVal2] = useState(0);
const answer = add(val1, val2);
return (
<div>
<input
className="name-input"
placeholder="์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์"
value={name}
type="text"
onChange={(e) => setName(e.target.value)}
/>
<input
className="value-input"
placeholder="์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={val1}
type="number"
onChange={(e) => setVal1(Number(e.target.value))}
/>
<input
className="value-input"
placeholder="์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={val2}
type="number"
onChange={(e) => setVal2(Number(e.target.value))}
/>
<div>{answer}</div>
</div>
);
}
// add.js
export const add = (num1, num2) => {
console.log("์ซ์๊ฐ ๋ค์ด์ต๋๋ค.");
return Number(num1) + Number(num2);
};
โฅ const [name, setName] = useState(""); ์์ name ์ด ๋ณ๊ฒฝ๋๋, ์ปดํฌ๋ํธ ์ ์ฒด๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ค.
๐useMemo ํ์ฉํ ์ฝ๋๐
โฅ `useMemo`๋ฅผ ์ด์ฉํ์ฌ `add `ํจ์์ ํธ์ถ์ ์ต์ํํ๋ค.
๊ทธ๋์ ์ด๋ฆ์ ์ ๋ ฅํ ๋๋ `add` ํจ์๊ฐ ํธ์ถ๋์ง ์์์ผ ์ต์ ํ๊ฐ ๋ ์ปดํฌ๋ํธ๊ฐ ๋์๋ค.
//App.js
import React, { useState } from "react";
import "./styles.css";
import { add } from "./add";
export default function App() {
const [name, setName] = useState("");
const [val1, setVal1] = useState(0);
const [val2, setVal2] = useState(0);
const answer = useMemo(() => add(val1, val2), [val1, val2]); // changed here!!!!!!
return (
<div>
<input
className="name-input"
placeholder="์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์"
value={name}
type="text"
onChange={(e) => setName(e.target.value)}
/>
<input
className="value-input"
placeholder="์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={val1}
type="number"
onChange={(e) => setVal1(Number(e.target.value))}
/>
<input
className="value-input"
placeholder="์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์"
value={val2}
type="number"
onChange={(e) => setVal2(Number(e.target.value))}
/>
<div>{answer}</div>
</div>
);
}
// add.js
export const add = (num1, num2) => {
console.log("์ซ์๊ฐ ๋ค์ด์ต๋๋ค.");
return Number(num1) + Number(num2);
};
์ซ์๋ฅผ ์ ๋ ฅํ์๋๋ง ์ฝ์์ฐฝ์ ๋ณํ๊ฐ ๋๋ค. (๋ ๋๋ง)
useCallback์ด๋?
useCallback๋ useMemo์ ๋์ผํ๊ฒ ๋ฉ๋ชจ์ด์ ์ด์ ๊ธฐ๋ฒ์ ์ด์ฉํ ๋ฆฌ์กํธ ๋ ๋๋ง ์ต์ ํ๋ฅผ ์ํ Hook์ด๋ค.
useMemo ๐ ๊ฐ์ ์ฌ์ฌ์ฉ์ ์ํด ์ฌ์ฉํ Hook
useCallback ๐ ํจ์์ ์ฌ์ฌ์ฉ์ ์ํด ์ฌ์ฉํ Hook
useCallback์ useMemo์ ๋น๊ตํ์ฌ ๋๋ฑํ ์์ค์ ์ต์ ํ๋ฅผ ๋๋ ์ ์๋ค.
์๋๋ฉด useCallback์ ํจ์๋ฅผ ํธ์ถ์ ํ์ง ์๋ Hook์ด ์๋๋ผ, ๊ทธ์ ๋ฉ๋ชจ๋ฆฌ ์ด๋๊ฐ์ ํจ์๋ฅผ ๊บผ๋ด์ ํธ์ถํ๋ Hook์ด๊ธฐ ๋๋ฌธ์ด๋ค.
์์ ์ฝ๋ ํด์
add ํจ์๋ props๋ก ๋์ด์จ x์ y ๊ฐ์ ๋ํด <div> ํ๊ทธ์ ๊ฐ์ ์ถ๋ ฅํ๊ณ ์๋ค.
์ด ํจ์๋ ํด๋น ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋๋ง๋ค ์๋กญ๊ฒ ๋ง๋ค์ด์ง๋ค.
function Calculator({x, y}){
const add = () => x + y;
return <>
<div>
{add()}
</div>
</>;
}
๋ง์ฝ ์์ ํด๋น ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋๋ผ๋ ๊ทธ ํจ์๊ฐ ์์กดํ๊ณ ์๋ ๊ฐ์ธ x์ y๊ฐ ๋ฐ๋์ง ์๋๋ค๋ฉด! ํจ์ ๋ํ ๋ฉ๋ชจ๋ฆฌ ์ด๋๊ฐ์ ์ ์ฅํด ๋๋ค๊ฐ ๋ค์ ๊บผ๋ด์ ์ธ ์ ์์ ๊ฒ์ด๋ค.
๐ ์ด๋ useCallback()๋ฅผ ์ฌ์ฉํด๋ณด์! ๐
useCallback Hook์ ์ฌ์ฉํ๋ฉด ๊ทธ ํจ์๊ฐ ์์กดํ๋ ๊ฐ๋ค์ด ๋ฐ๋์ง ์๋ ํ ๊ธฐ์กด ํจ์๋ฅผ ๊ณ์ํด์ ๋ฐํํ๋ค.
์ฆ, x์ y๊ฐ์ด ๋์ผํ๋ค๋ฉด ๋ค์ ๋ ๋๋ง ๋ ์ด ํจ์๋ฅผ ๋ค์ ์ฌ์ฉํ๋ค.
/* useCallback๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์๋ ๊ผญ importํด์ ๋ถ๋ฌ์์ผ ํฉ๋๋ค. */
import React, { useCallback } from "react";
function Calculator({x, y}){
const add = useCallback(() => x + y, [x, y]);
return <>
<div>
{add()}
</div>
</>;
}
useCallback๋ ํจ์์ ๋จ์ํ ์ปดํฌ๋ํธ ๋ด์์ ํจ์๋ฅผ ๋ฐ๋ณตํด์ ์์ฑํ์ง ์๊ธฐ ์ํด์ ์ฌ์ฉํ๋ ๊ฒ์ ํฐ ์๋ฏธ๊ฐ ์๊ฑฐ๋ ์คํ๋ ค ์ํด์ธ ๊ฒฝ์ฐ๋ ์๋ค.
useCallback ๋ฅผ ๋ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ๐ ํจ์ ์์ ์ปดํฌ๋ํธ์ props๋ก ํจ์๋ฅผ ์ ๋ฌํด์ค ๋ ์ด useCallback์ ์ฌ์ฉํ๊ธฐ!!
JavaScript์์ ๊ฐ์ฒด๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ ๋ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ ์๋๋ผ ๊ฐ์ ์ฃผ์๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์, ๋ฐํํ๋ ๊ฐ์ด ๊ฐ์ ์ง๋ผ๋ ์ผ์น์ฐ์ฐ์๋ก ๋น๊ตํ์ ๋ false๊ฐ ์ถ๋ ฅ๋๋ค.
React๋ JavaScript ์ธ์ด๋ก ๋ง๋ค์ด์ง ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ์ ์ผ๋ก JavaScript์ ๋ฌธ๋ฒ์ ๋ฐ๋ผ๊ฐ๋ค.
๋ฐ๋ผ์ useCallback์ ์ด์ฉํด ํจ์ ์์ฒด๋ฅผ ์ ์ฅํด์ ๋ค์ ์ฌ์ฉํ๋ฉด ํจ์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๊ฐ์ ์ ์ฅํ๋ค๊ฐ ๋ค์ ์ฌ์ฉํ๋ค๋ ๊ฒ๊ณผ ๊ฐ๋ค๊ณ ๋ณผ ์ ์๋ค. ๋ฐ๋ผ์ React ์ปดํฌ๋ํธ ํจ์ ๋ด์์ ๋ค๋ฅธ ํจ์์ ์ธ์๋ก ๋๊ธฐ๊ฑฐ๋ ์์ ์ปดํฌ๋ํธ์ prop์ผ๋ก ๋๊ธธ ๋ ์์์น ๋ชปํ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋ง์ ์ ์๋ค.
=> useCallback๊ณผ ์ฐธ์กฐ ๋๋ฑ์ฑ
useCallback์ ํ์์ฑ
๊ฐ์ ์ปดํฌ๋ํธ ์์ ์๋ state์ค ํ๋๋ผ๋ ๋ณํ๊ฐ ์์ผ๋ฉด ๊ทธ ์ปดํฌ๋ํธ ์ ์ฒด๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋๋ฐ, ์ด๋ ๋ถํ์ํ๋ค!!
์ฌ๊ธฐ์๋ button์ด ํด๋ฆญ๋๋ฉด ์ ํ ๊ด๋ จ์๋ input ์์๊ฐ ๋ ๋๋ง ๋๊ณ ์๋ค.
์ด๋ useCallback์ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ํธ์ถ์ ์ค์ผ ์ ์๋ค! ๐
//App.js
import { useState } from "react";
import "./styles.css";
import List from "./List";
export default function App() {
const [input, setInput] = useState(1);
const [light, setLight] = useState(true);
const theme = {
backgroundColor: light ? "White" : "grey",
color: light ? "grey" : "white"
};
const getItems = () => {
return [input + 10, input + 100];
};
const handleChange = (event) => {
if (Number(event.target.value)) {
setInput(Number(event.target.value));
}
};
return (
<>
<div style={theme} className="wall-paper">
<input
type="number"
className="input"
value={input}
onChange={handleChange}
/>
<button
className={(light ? "light" : "dark") + " button"}
onClick={() => setLight((prevLight) => !prevLight)}
>
{light ? "dark mode" : "light mode"}
</button>
<List getItems={getItems} />
</div>
</>
);
// List.js
import { useState, useEffect } from "react";
function List({ getItems }) {
/* Initial state of the items */
const [items, setItems] = useState([]);
/* This hook sets the value of items if
getItems object changes */
useEffect(() => {
console.log("์์ดํ
์ ๊ฐ์ ธ์ต๋๋ค.");
setItems(getItems());
}, [getItems]);
/* Maps the items to a list */
return (
<div>
{items.map((item) => (
<div key={item}>{item}</div>
))}
</div>
);
}
export default List;
๐useCallback ํ์ฉํ ์ฝ๋๐
โฅ `useCallback`๋ฅผ ์ด์ฉํ์ฌ `getItem ` ํธ์ถ์ ์ต์ํํ๋ค.
์์ ์ปดํฌ๋ํธ์ props๋ก ํจ์๋ฅผ ์ ๋ฌํด์ค ๋ ์ด useCallback์ ์ฌ์ฉํ๊ธฐ๊ฐ ์ข๋ค.
//App.js
import { useState } from "react";
import "./styles.css";
import List from "./List";
export default function App() {
const [input, setInput] = useState(1);
const [light, setLight] = useState(true);
const theme = {
backgroundColor: light ? "White" : "grey",
color: light ? "grey" : "white"
};
const getItems = useCallback(() => [input + 10, input + 100], [input]); // changed here!!!!!!
const handleChange = (event) => {
if (Number(event.target.value)) {
setInput(Number(event.target.value));
}
};
return (
<>
<div style={theme} className="wall-paper">
<input
type="number"
className="input"
value={input}
onChange={handleChange}
/>
<button
className={(light ? "light" : "dark") + " button"}
onClick={() => setLight((prevLight) => !prevLight)}
>
{light ? "dark mode" : "light mode"}
</button>
<List getItems={getItems} />
</div>
</>
);
// List.js
import { useState, useEffect } from "react";
function List({ getItems }) {
/* Initial state of the items */
const [items, setItems] = useState([]);
/* This hook sets the value of items if
getItems object changes */
useEffect(() => {
console.log("์์ดํ
์ ๊ฐ์ ธ์ต๋๋ค.");
setItems(getItems());
}, [getItems]);
/* Maps the items to a list */
return (
<div>
{items.map((item) => (
<div key={item}>{item}</div>
))}
</div>
);
}
export default List;
๋ฒํผ์ ์๋ฌด๋ฆฌ ๋๋ฌ๋ ์ฝ์์ฐฝ์๋ ๋ณํ๊ฐ ์๋ค.
๐ ์๋ชป๋ ๊ฐ๋ ์ ๋ฌ์ด ์๋ค๋ฉด ๋๊ธ ๋ถํ๋๋ฆฝ๋๋ค. ์ ์ ์ฑ์ฅ์ ํฐ ๋์์ด ๋ฉ๋๋ค๐ค
'๐ฅFrontEnd > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
useRef๋, useRef ์ฌ์ฉ๋ฐฉ๋ฒ, useRef ์ฌ์ฉ ์์ (0) | 2022.07.27 |
---|---|
Custom Hook, Custom Hook ์ฅ์ , ๊ท์น (0) | 2022.07.27 |
๋ฆฌ์กํธ์ ๊ฐ์ DOM, React๊ฐ DOM ํธ๋ฆฌ๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ, key ๊ฐ์ ์ค์ ํ๋ ์ด์ (0) | 2022.07.27 |
๋ฆฌ์กํธ ํ ์ฌ์ฉ ๊ท์น (0) | 2022.07.26 |
๋ฆฌ์กํธ Context ,๋ฆฌ์กํธ ์ปจํ ์คํธ์ ํ๊ณ (0) | 2022.07.26 |