1. ExternalStore
useState ๋ฅผ ์ ๊ฑฐํ์ฌ ์ํ๋ฅผ ๊ด๋ฆฌํด๋ณด์
React์์๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๋ค ๋ณ์์ ๊ฐ์ด ๋ณํํ์์ ๋(๋ณดํต ์ ์ ์ ์กฐ์์ผ๋ก ์ธํ), UI์ ํด๋น ๊ฐ์ ๋ฐ์ํ๊ธฐ ์ํด์๋ useStore ๋ผ๋ React์์ ์ ๊ณตํ๋ hook์ ์ฌ์ฉํด์ผ ํ๋ค.
๊ทธ๋ ์ง ์๊ณ , ์ผ๋ฐ์ ์ผ๋ก ๋ณ์๋ฅผ ์ ์ํ ํ์ ์ด๋ค ์ด๋ฒคํธ์ ๋ฐ๋ผ์ ๊ฐ์ ๋ณํ์์ผฐ์ ๋๋ UI์ ํด๋น ๊ฐ์ ๋ฐ์ํ ์ ์๋ค. ๋ณ๊ฒฝ๋ ๊ฐ์ ์ธ์ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์, ๋ฆฌ๋ ๋๋ง๋์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
React์์๋ ๋ก์ปฌ state, ๊ทธ๋ฌ๋๊น ๋ณ์์ ์ํ๋ฅผ ๋ณ๊ฒฝํด์๋ ์๋๋ฉฐ, useState๋ฅผ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค.
let count = 0;
export default function Counter() {
const handleClick = () => {
count += 1;
};
return (
<div>
<p>{count}</p>
<button type='button' onClick={handleClick}>
Increase
</button>
</div>
);
}
๋ณ๊ฒฝ๋ ์ํ์ ๊ฐ์ ๋ฐ์ํ์ฌ, ๋ฆฌ๋ ๋๋ง ๋๋๋ก ํ๊ธฐ ์ํด์๋ useState ๋ฅผ ์ฌ์ฉํ๋ค.
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount((prev) => prev + 1);
};
return (
<div>
<p>{count}</p>
<button type='button' onClick={handleClick}>
Increase
</button>
</div>
);
}
๊ทธ๋ฌ๋ฉด useState๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ฆฌ๋ ๋๋ง์ ๊ฐ์ ํ์ฌ UI์ ๋ฐ์ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์๊น? useReducer๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฅํ๋ค.
import { useReducer } from 'react';
let count = 0;
function increase() {
count += 1;
}
export default function Counter() {
const [ignored, forceUpdate] = useReducer((x) => x + 1, 0);
const handleClick = () => {
increase();
forceUpdate();
};
return (
<div>
<p>{count}</p>
<button type='button' onClick={handleClick}>
Increase
</button>
</div>
);
}
๋ฒํผ์ ํด๋ฆญํ์ ๋ ์ฆ๊ฐํ count ์ ํ๋ฉด์ ์ ๋ฐ์์ด ๋๋ค. ํฅ๋ฏธ๋ก์ด ๊ฒ์ useReducer ์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ ํจ์์์ ํ๊ณ ์๋ ์ญํ ์ ์๋ฏธ๊ฐ ์๋ค๋ ๊ฒ์ด๋ค. +1์ ํด๋ ๋๊ณ , ๋น๋ฌธ์์ด์ ๋ํด๋ ๋๋ค. ์ฆ, ์ฌ๊ธฐ์ useReducer ๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ํ ์ผ๋ก์จ๋ง ์ฌ์ฉ๋๋ค๋ ์ ์ด๋ค.
์ฐธ๊ณ ๋ก useState ๋ ๋ด๋ถ์ ์ผ๋ก useReducer๋ฅผ ์ฌ์ฉํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ค์ ํ ๋ฒ ์ฝ๋๋ฅผ ๊ณ ์ณ๋ณด์.
import { useEffect, useReducer, useState } from 'react';
let count = 0;
function increase() {
count += 1;
}
export default function Counter() {
const [state, setState] = useState(0);
const forceUpdate = () => {
setState(state + 1);
};
useEffect(() => {
console.log('test');
});
const handleClick = () => {
increase();
// ๊ฐ์ ๋ก ๋ฆฌ๋ ๋๋ง
forceUpdate();
};
return (
<div>
<p>{count}</p>
<button type='button' onClick={handleClick}>
Increase
</button>
</div>
);
}
useReducer๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , forceUpdate๋ผ๋ ํจ์ ์์์ setState ๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ฌ, ๊ฐ์ ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ์ํฌ์๋ ์๋ค. ํ๋ฉด์ ๋ณด์ด๋ ๊ฐ์ increase ํจ์์์ ์ฒ๋ฆฌํ ์ฆ๊ฐ๋ ๋ณ์์ ๊ฐ์ด๋ค. forceUpdate๋ผ๋ ํจ์๋ฅผ Hook ์ผ๋ก ๋ง๋ค๋ฉด ์๋์ ๊ฐ์ ๋ชจ์์ด ๋๋ค.
// hooks/useForceUpdate.ts
import { useState } from 'react';
export default function useForceUpdate() {
const [state, setState] = useState({});
const forceUpdate = () => {
// useState ์ ๊ธฐ๋ณธ ๊ฐ์ 0์ด ์๋ object ๋ก ์ก๊ณ , setState ์์ object ๋ฅผ spread
// ์ฐ์ฐ์๋ก destructing ํ๋ฉด ์๋ก์ด ๊ฐ์ฒด๊ฐ ๋๊ธฐ ๋๋ฌธ์, ๋ ๋จ์ํ ์ฝ๋๊ฐ ๋๋ค.
// setState({ ...state });
// ์์ ์ฝ๋ ์ฃผ์์ฒ๋ฆฌํ๊ณ ... ์๋์ ๊ฐ์ด๋ง ์จ์ค๋, ์๋ก์ด ๊ฐ์ฒด๊ฐ ๋์ด ์ํ๋ฅผ ์
๋ฐ์ดํธํ์ฌ,
// ๋ฆฌ๋ ๋๋ง ๋๋๋ก ํ๋ค.
setState({});
};
return forceUpdate;
}
// component/Counter.tsx
import useForceUpdate from '../hooks/useForceUpdate';
let count = 0;
function increase() {
count += 1;
}
export default function Counter() {
const forceUpdate = useForceUpdate();
const handleClick = () => {
increase();
forceUpdate();
};
return (
<div>
<p>{count}</p>
<button type='button' onClick={handleClick}>
Increase
</button>
</div>
);
}
์ด๋ ๊ฒ ํ๋ฉด Counter ์ปดํฌ๋ํธ์์๋ ๋์ด์ useState ๊ฐ ํ์์์ด์ง๊ณ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๊ฐ์ง๊ณ ์๋ ๋ก์ปฌ ๋ณ์๋ฅผ ์ ๋ฐ์ดํธํ์ฌ UI์ ๋ฐ์ํ ์ ์๋ค.
๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ ๋ฌธ์ ๋ ํ ์ผ๋ก ๋ถ๋ฆฌํ useReducer ์ ํจ์ ์ธ์์์ ๊ณ์ setState ํจ์๋ฅผ ํตํด์, ์๋ฏธ์๋ ๊ฐ์ ์ ๋ฐ์ดํธ๊ฐ ๋๋ค๋ ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ useReducer ์ ์ญํ ์ ๋จ์ํ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ๋ฆฌ๋ ๋๋ง ํ๋ ๊ฒ์ด๊ณ , useReducer ์ ํจ์ ์ธ์ ๊ฐ์์ ๋ณ๊ฒฝํ๊ณ ์๋ ์ํ๋ ํน๋ณํ ์ผ์ ํ๋ ๊ฒ์ด ์๋๋ค.
useForceUpdate ๋ฅผ ๋ฆฌํํ ๋งํด๋ณด์.
// hooks/useForceUpdate.ts
import { useState, useCallback } from 'react';
export default function useForceUpdate() {
const [, setState] = useState({});
return useCallback(() => setState({}), []);
}
useCallback ์ ์ฌ์ฉํ์ฌ, useCallback ์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ ํจ์๊ฐ ๋งค๋ฒ ์๋ก์ด ํจ์๊ฐ ์๋๋๋ก ๋ง๋ค์ด์ฃผ์๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก, ์์ ์ฝ๋์์๋ ๋น์ง๋์ค ๋ก์ง๊ณผ UI์ ๋ํ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๊ฐ ์ด๋ฃจ์ด์ก๋ค.
Last updated