set-state-in-render

๋ Œ๋”๋ง ์ค‘์— ๋ฌด์กฐ๊ฑด state๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ถ”๊ฐ€ ๋ Œ๋”๋ง๊ณผ ์ž ์žฌ์ ์ธ ๋ฌดํ•œ ๋ Œ๋”๋ง ๋ฃจํ”„๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทœ์น™ ์„ธ๋ถ€ ์‚ฌํ•ญ

๋ Œ๋”๋ง ์ค‘์— ๋ฌด์กฐ๊ฑด setState๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ˜„์žฌ ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ๋ Œ๋”๋ง์ด ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์•ฑ์„ ์ถฉ๋Œ์‹œํ‚ค๋Š” ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์œ„๋ฐ˜ ์‚ฌ๋ก€

์ž˜๋ชป๋œ ์˜ˆ์‹œ

// โŒ ๋ Œ๋”๋ง ์ค‘์— ์ง์ ‘ ๋ฌด์กฐ๊ฑด setState
function Component({value}) {
const [count, setCount] = useState(0);
setCount(value); // ๋ฌดํ•œ ๋ฃจํ”„!
return <div>{count}</div>;
}

์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์‹œ

// โœ… ๋ Œ๋”๋ง ์ค‘์— ํŒŒ์ƒ
function Component({items}) {
const sorted = [...items].sort(); // ๋ Œ๋”๋ง ์ค‘์— ๊ณ„์‚ฐ
return <ul>{sorted.map(/*...*/)}</ul>;
}

// โœ… ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ state ์„ค์ •
function Component() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}

// โœ… state๋ฅผ ์„ค์ •ํ•˜๋Š” ๋Œ€์‹  props์—์„œ ํŒŒ์ƒ
function Component({user}) {
const name = user?.name || '';
const email = user?.email || '';
return <div>{name}</div>;
}

// โœ… ์ด์ „ ๋ Œ๋”๋ง์˜ props์™€ state๋กœ๋ถ€ํ„ฐ ์กฐ๊ฑด๋ถ€๋กœ state ํŒŒ์ƒ
function Component({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selection, setSelection] = useState(null);

const [prevItems, setPrevItems] = useState(items);
if (items !== prevItems) { // ์ด ์กฐ๊ฑด์ด ์œ ํšจํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค
setPrevItems(items);
setSelection(null);
}
// ...
}

๋ฌธ์ œ ํ•ด๊ฒฐ

state๋ฅผ prop๊ณผ ๋™๊ธฐํ™”ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค

์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋Š” ๋ Œ๋”๋ง ํ›„ state๋ฅผ โ€œ์ˆ˜์ •โ€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์นด์šดํ„ฐ๊ฐ€ max prop์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š๋„๋ก ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

// โŒ ์ž˜๋ชป๋œ ์˜ˆ์‹œ: ๋ Œ๋”๋ง ์ค‘์— ์ œํ•œ
function Counter({max}) {
const [count, setCount] = useState(0);

if (count > max) {
setCount(max);
}

return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}

count๊ฐ€ max๋ฅผ ์ดˆ๊ณผํ•˜์ž๋งˆ์ž ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

๋Œ€์‹  ์ด ๋กœ์ง์„ ์ด๋ฒคํŠธ(state๊ฐ€ ์ฒ˜์Œ ์„ค์ •๋˜๋Š” ๊ณณ)๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด state๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ˆœ๊ฐ„์— ์ตœ๋Œ“๊ฐ’์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// โœ… ์—…๋ฐ์ดํŠธํ•  ๋•Œ ์ œํ•œ
function Counter({max}) {
const [count, setCount] = useState(0);

const increment = () => {
setCount(current => Math.min(current + 1, max));
};

return <button onClick={increment}>{count}</button>;
}

์ด์ œ setter๋Š” ํด๋ฆญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ๋งŒ ์‹คํ–‰๋˜๊ณ , React๋Š” ์ •์ƒ์ ์œผ๋กœ ๋ Œ๋”๋ง์„ ์™„๋ฃŒํ•˜๋ฉฐ, count๋Š” ์ ˆ๋Œ€ max๋ฅผ ๋„˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋“œ๋ฌธ ๊ฒฝ์šฐ์ง€๋งŒ ์ด์ „ ๋ Œ๋”๋ง์˜ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ state๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ ์กฐ๊ฑด๋ถ€๋กœ state๋ฅผ ์„ค์ •ํ•˜๋Š” ์ด ํŒจํ„ด์„ ๋”ฐ๋ฅด์„ธ์š”.