const obj = {id: 'me', age: 20};
console.log(...obj);
์์ ๊ฐ์ ์ฝ๋๋ ์ด๋ค ์ถ๋ ฅ์ ํ ๊น?
์ฌ์ค ์ด ์ฝ๋๋ ํ์ ์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค. obj๋ iterableํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. spread operator๋ ๋ฐฐ์ด์ด๋, ๋ฌธ์์ด ๋ฑ iterableํ ๊ฐ์ฒด์์ ์ฌ์ฉํ ์ ์๋ค.
const arr = [1, 2, 3, 4, 5];
console.log({ ...arr });
์ต์ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์์๋ spread operator๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ค. ์์ ์์์์๋ key-value ํํ๋ก index: item์ธ object๊ฐ ๋ง๋ค์ด์ง๋ค.
const person = { name: 'lee', age: 20 };
const info = { address: 'incheon' };
const me = { ...person, ...info };
๋ค์๊ณผ ๊ฐ์ ๋ฌธ๋ฒ์ ์ด์ฉํ๋ฉด ์๋ก์ด obj์ ์์ฑ๋ค์ ์ด๊ฑฐํ ์ ์๋ ๊ฒ์ด๋ค.
๋ด๊ฐ ๊ฐ์ง ์๋ฌธ์ ๋ค์๊ณผ ๊ฐ๋ค.
const withCheckPermission = (TargetComponent) => {
return function WithCheckPermission(props) {
const [permission, setPermisson] = useState(null);
useEffect(() => {
async function checkPermisson() {
const result = await fetch("/api/checkPermisson").then((res) =>
res.json()
);
setPermisson(result);
}
checkPermisson();
}, []);
return <TargetComponent {...props} permission={permission} />;
};
};
HOC์ ๋ํ ์์๋ฅผ ์์ฑํ๋ ์ค {...props} ๋ถ๋ถ์ด ๋์ ๊ฑฐ์ฌ๋ ธ๋ค. ๋น์ฐํ๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ธ๋ฐ ์ด๋ป๊ฒ ์ ๋ฐ ๋ฌธ๋ฒ์ด ๊ฐ๋ฅํ ๊ฑด์ง ์ดํด๊ฐ ๋์ง ์๋๋ค.
JSX์์ ์ค๊ดํธ๋ ์ผ๋ฐ์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ธฐ ์ํจ์ด๋ผ๊ณ ๋ค์๋ค. ๊ทธ๋ฐ๋ฐ props๋ iterableํ์ง ์์ ๊ฐ์ฒด์ธ๋ฐ ์ด๋ป๊ฒ spread operator๋ฅผ ์ด์ฉํด ์ ๊ฐํ ๊น?
Spread Attributes
If you already have props as an object, and you want to pass it in JSX, you can use ... as a โspreadโ syntax to pass the whole props object. These two components are equivalent:function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />; }
You can also pick specific props that your component will consume while passing all other props using the spread syntax.
์ฐธ๊ณ ๋ก ๊ณต์ ๋ฌธ์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋์์๋ค.
<Component />
Component();
๋์ ์ฐจ์ด๋ ๋ญ๊น? ์ผ๋จ ํจ์ ํธ์ถ๊ณผ ์ปดํฌ๋ํธ ํธ์ถ์ ๋ค๋ฅด๋ค. ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ์์๋ฅผ ์ด์ฉํด ์์๋ณด์.
ํด๋น ๋ด์ฉ์ React: Calling functional components as functions์ ์ฝ๊ณ ์์ฑ๋์๋ค.
const Counter = ({ onClick }) => {
const [count, setCount] = useState(0);
const incrementTotal = () => {
setTotal((prev) => prev + 1);
};
const increment = () => {
setCount((prev) => prev + 1);
onClick();
};
return (
<div className='Counter'>
<div>{count}</div>
<button onClick={increment}>+</button>
</div>
);
};
const ComponentTest = () => {
const [total, setTotal] = useState(0);
return (
<div>
<div>The Total is {total}</div>
<Counter onClick={incrementTotal} />
<Counter onClick={incrementTotal} />
<Counter onClick={incrementTotal} />
</div>
);
};
๊ฐ๊ฐ์ ์นด์ดํฐ๋ง๋ค total๊ณผ ์์ ์ count๋ฅผ ์ฆ๊ฐ์ํค๊ณ ์๋ค. ๋ณ ๋ฌธ์ ์์ด ์๋๋๋ค. ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์์๊ฐ ์ถ๊ฐ๋๋ค๋ฉด ์ด๋จ๊น?
const ComponentTest = () => {
const [total, setTotal] = useState(0);
const incrementTotal = () => {
setTotal((prev) => prev + 1);
};
const CounterInComponent = ({ onClick }) => {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prev) => prev + 1);
onClick();
};
return (
<div className='Counter'>
<div>{count}</div>
<button onClick={increment}>+</button>
</div>
);
};
return (
<div>
<div>The Total is {total}</div>
...
<CounterInComponent onClick={incrementTotal} />
</div>
);
};
์ปดํฌ๋ํธ ์์์ ์นด์ดํฐ๋ฅผ ์์ฑํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ฉด ์์์น ๋ชปํ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๋ค.
total์ ์ฆ๊ฐํ์ง๋ง CounterInComponent์ count๋ ์ฆ๊ฐํ์ง ์๋๋ค. ์ด ํ์์ ์์ธ์ ๊ทธ๋๋ ๋ช ๋ฐฑํ๋ค.
total์ด ์ฆ๊ฐํ๋ฉด ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ๊ณ CounterInComponent ๋ํ ์ฌ์ ์ธ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ์ฌ์ ์ธ๋ CounterInComponent์ ๊ธฐ์กด์ CounterInComponent๋ ๋ค๋ฅธ ์ฐธ์กฐ์ด๊ธฐ ๋๋ฌธ์ ์ด๊ธฐํ๋๋ ๊ฒ์ด๋ค.
{CounterInComponent({ onClick: incrementTotal })}
๋ค์๊ณผ ๊ฐ์ด ์ผ๋ฐ์ ์ธ ํจ์ํธ์ถ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณด์. ๋ฌธ์ ๊ฐ ์ฌ๋ผ์ก๋ค...
๊ทธ๋ฆฌ๊ณ React devtools๋ฅผ ํ์ธํ๋ฉด ์ ๊ธฐํ ํ์์ด ๋ฒ์ด์ง๋ค.
์๋ ์ปดํฌ๋ํธ ํํ๋ก ํธ์ถํ ๊ฒฐ๊ณผ, ์๋๋ ์ผ๋ฐ ํจ์ ํธ์ถ๋ก ๋ถ๋ฌ์จ ๊ฒฐ๊ณผ์ด๋ค.
์ผ๋ฐ ํจ์ํธ์ถ์ ๋ฆฌ์กํธ๊ฐ ์ปดํฌ๋ํธ๋ก ์ธ์ํ์ง ์๋๋ค. ์ด๊ฒ์ด ๋ปํ๋ ๊ฑด ๋ฆฌ์กํธ๊ฐ ํด๋น ์์์ ๋ณํ๋ฅผ ๊ฐ์งํ์ง ์๋๋ค๋ ๊ฒ์ด๋ค!
๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง์ผ๋ก CounterInComponent๋ ๋ค์ ์ ์ธ๋์ง๋ง ๋ฆฌ์กํธ๋ ๊ทธ๊ฒ์ด ์๋ก์ด ์ฐธ์กฐ์ด๋ ๋ง๋ ๊ด์ฌํ์ง ์๋๋ค.
๊ทธ๋ฅ ์ผ๋ฐ์ ์ธ TextNode์ฒ๋ผ ์ผ๋ฐํจ์ ํธ์ถ์ ์ทจ๊ธํด๋ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
์๋ฌดํผ ๋ด๊ฐ ์ด๋ฐ ํฌ์คํธ๋ฅผ ์ฐพ์ ๋ณธ ์ด์ ๋ ์ปดํฌ๋ํธ๊ฐ ์ผ๋ฐ์ ์ธ function call์ด๊ณ {...props}์ ์ ๊ฐ ์ฐ์ฐ์๊ฐ rest operator ํํ๋ก ์ ๋ฌ๋๋ ์๋ฌธ์ด ๋ค์ด์์ด๋ค.
babel์ด ์ผ๋ฐ์ ์ธ function call ๋ณํํด์ค๋ค๊ณ ๊ฐ์ ํ๋ฉด ์ดํดํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ ์ฌํ๊ธด ํ์ง๋ง ์ผ๋จ ๊ฒฐ๋ก ์ ์๋๋ค๋ ์ชฝ์ผ๋ก ๊ธฐ์ธ์๋ค.
<Component {...props1} {...props2} />
์๊ฐํด๋ณด๋ ๋ค์๊ณผ ๊ฐ์ ์ฌ์ฉ๋ ๊ฐ๋ฅํ๋ค. ์ ๊ฐ ์ฐ์ฐ์๋ฅผ ๋ ๋ฒ ์ฌ์ฉํด ์ ๋ฌํด๋ ๋ฌธ๋ฒ์ ์ธ ์ค๋ฅ๋ ์๋ค.
rest operator๋ ์๋ ๊ฒ ๊ฐ๋ค.
const obj1 = { name: "lee" };
<Component {...obj1} name='kim' />
๋ค์๊ณผ ๊ฐ์ ์คํ์ ํ๋ค ์ค๋ง๋ฆฌ๊ฐ ์กํ๋ค. ์์ ์ฝ๋์์ name props์ ๊ฒฐ๊ณผ๋ kim์ด๋ค. ๋ค์ ์๋ ๋ ์์ด ์ ์ฉ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ props๋ ๊ฐ์ฒด์ด๋ค.
const person = { name: 'lee', age: 20 };
const info = { address: 'incheon' };
const me = { ...person, ...info };
์์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ์์์์ ๋ค์๊ณผ ๊ฐ์ด ์๋ก์ด ๊ฐ์ฒด์ ์์ฑ์ ์ถ๊ฐํ ์ ์์๋ค.
props๋ ๋น์ทํ ํํ๋ก ์๋ํ๋ ๊ฒ ์๋๊น?
๊ธฐ์กด props ๊ฐ์ฒด์ {...obj}๋ฅผ ์ถ๊ฐํ๋ ํ์์ผ๋ก ํ๋ค๋ฉด key=value๋ก ์ ๋ฌํ๋ ๊ฒ๊ณผ ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ์ ํํ๋ก ๋์ํ๋ค.
๋๊ณ ๋์ ๋ด๋ฆฐ ๊ฒฐ๋ก ์ด์ง๋ง ํ๋นํ ๊ฒฐ๋ก ์ธ ๊ฒ ๊ฐ๋ค!
Babel playground์ ์ ๋ต์ด ๋์์์๋ค์ ใ
ใ