2024-03-14.md
๐กDIL: ๋ชจ๋ ๋ฆฌ์กํธ ๋ฅ ๋ค์ด๋ธ, 2์ฃผ์ฐจ-4
์คํฐ๋: ์๊ฐ CS, https://github.com/monthly-cs/2024-03-modern-react-deep-dive
์ค๋ ์งํ: ๊ฐ์ธ๊ณต๋ถ
DIL-week2-4_2024-03-14
| DIL ์ฃผ์ฐจ | ๋ฒ์ | ๋ด์ฉ | ์ค๋์ฐจ ์ง๋ | | -------- | ------ | ------------------------------- | ----------- | | 2์ฃผ์ฐจ | 3, 5์ฅ | ๋ฆฌ์กํธ ํ ๊ณผ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ | 219p~228p |
์ค๋ ์ฝ์ ๋ด์ฉ์ markdown์ผ๋ก ๊ฐ๋จํ ๋ฉ๋ชจ
์ฝ์ ์๊ฐ: 11์~12์
๋ ํผ๋ฐ์ค
- https://react.dev/reference/react/useReducer
React Hook ํํค์น๊ธฐ
useContext
Context๋?
-
props drilling์? ๋ฒ๊ฑฐ๋ก์
-
createContext ํ ํ์ ์ปดํฌ๋ํธ์ ์ ๋ฌ
<Context.Provider value={{ foo: "bar " }}> <ChildComponent /> </Context.Provider> ... export default function ChildComponent (){ const value = useContext(Context); ... }
context๋ฅผ ๋ณ๋์ ์ฝ๋๋ก ๊ฐ์ธ๊ธฐ
-
์ปดํฌ๋ํธ๊ฐ ์คํ๋ ๋ ์ฝํ ์คํธ๊ฐ ์กด์ฌํ์ง ์์์ ์๋ฌ ๋ฐ์ํ๋ ๊ฒฝ์ฐ ์์
-
์ด๊ธฐํ ์ฌ๋ถ ํ์ธ
-
TS ํ์ ์ถ๋ก
-
์์์ Provider๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ๋๋ฒ๊น
function useMyContext() { const context = useContext(MyContext); if (context === undefined) { throw new Error("Context Exception"); } return context; } ... export default function ChildComponent (){ const { foo } = useMyContext(); ... }
useContext๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์์
- ์์กด์ฑ: Provider์ ์์กดํ์ฌ ์ฌํ์ฉ์ด ์ด๋ ค์์ง๋ค.
- ์ํ๊ด๋ฆฌ API๊ฐ ์๋
- ์กฐ๊ฑด1: ์ด๋ ํ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค๋ฅธ ์ํ๋ฅผ ๋ง๋ค์ด๋ธ๋ค => x
- ์กฐ๊ฑด2: ์ํ ๋ณํ๋ฅผ ์ต์ ํํ๋ค => x. ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ๋ฆฌ๋๋๋ง๋๋ ๊ณ ์ง์ ์ธ ๋ฌธ์ (props ์ ๋ฌ์ด๊ธฐ ๋๋ฌธ, memo๋ก ํด๊ฒฐ ๊ฐ๋ฅ. ๊ตณ์ด?)
useContext๋ก ์ฃผ์ ํ ์ํ๋ฅผ ์ฌ์ฉํ ๋ฟ, ๊ทธ ์์ฒด๋ก ๋๋๋ง ์ต์ ํ์ ์๋ฌด๋ฐ ๋์์ด ๋์ง ์๋๋ค.
useReducer
- https://react.dev/reference/react/useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init?) // init์ ๊ฒ์ผ๋ฅธ ์ด๊ธฐํ
- state์ ์ฌ์ ์ ์ ์๋ dispatcher๋ก๋ง ์์ ํ ์ ์๋๋ก ํ๋ค.
- state์ ๊ฐ์ ๋ํ ์ ๊ทผ์ ๋ฏธ๋ฆฌ ์ ์๋ dispatcher, ์ฆ ์ปดํฌ๋ํธ์์๋ง ๊ฐ๋ฅํ๊ฒ ํจ
- state ๊ฐ์ ๋ณ๊ฒฝํ๋ ์๋๋ฆฌ์ค๋ฅผ ์ ํ / ๋ณ๊ฒฝ์ ๋น ๋ฅด๊ฒ ํจ
- ์ ์ฐ๋?
- ์ฌ๋ฌ ๊ฐ์ state์ ๋ฌถ์ด์ ๊ด๋ฆฌ
- state ์ฌ์ฉ ๋ก์ง๊ณผ ๋น์ฆ๋์ค ๋ก์ง ๋ถ๋ฆฌ
type State = {
color: string;
};
type Action = { type: "day" | "night"; payload: State };
function init(count: State): State {
return count;
}
const initialState: State = { count: 0 };
function reducer(state: State, action: Action): State {
switch (action.type) {
case "day":
return { color: "#ffffff" };
case "night":
return { color: "#222222" };
default:
throw new Error("Unexpected action type");
}
}
export default function App() {
const [state, dispatcher] = useReducer(reducer, initialState, init);
}
useReducer๋ก userState ๋ง๋ค๊ธฐ
function reducer(prevState, newState) {
return typeof newState === "function" ? newState(prevState) : newState;
}
function init(intialArg) {
return typeof intialArg === "function" ? intialArg() : intialArg;
}
function useState(intialArg) {
return useReducer(reducer, intialArg, init);
}
userState๋ก useReducer ๋ง๋ค๊ธฐ
const useReducer = (reducer, initialArg, init) => {
const [state, setState] = useState(
init ? () => init(initialArg) : initialArg
);
const dispatch = useCallback(
(action) => setState((prev) => reducer(prev, action)),
[reducer]
);
return useMemo(() => [state, dispatch], [state, dispatch]);
};
| ๊ธฐ์ค | useState | useReducer | | ------------------ | ---------------------------------------------------------- | ---------------------------------------------------------------------------------- | | ์ ์ | ๋จ์ผ ์ํ ๊ฐ์ ์ฌ์ฉ | ์ฌ๋ฌ ํ์ ๊ฐ ์๋ ๋ณต์กํ ์ํ ๋ก์ง ๊ด๋ฆฌ์ ์ ํฉ | | ์ฌ์ฉ ์ฌ๋ก | ๊ฐ๋จํ ์ํ ๋ก์ง๊ณผ ๊ฐ์ ์ฌ์ฉ | ์ํ ์ ๋ฐ์ดํธ ๋ก์ง ๋ณต์กํ๊ฑฐ๋ ์ฌ๋ฌ ์ํ ์๋ก ์์กด์ ์ผ ๋ ์ฌ์ฉ | | ์ํ ๊ด๋ฆฌ | ๋จ์ผ ๊ฐ(๊ฐ์ฒด, ๋ฐฐ์ด, ๊ธฐํ) ๊ด๋ฆฌ | ์ก์ ์ ํตํ ์ํ ์ ๋ฐ์ดํธํ๋ ๋ฆฌ๋์ ํจ์ ์ฌ์ฉํ์ฌ ๋ณต์กํ ์ํ ๊ด๋ฆฌ | | ์ฌ์ฉ ๋ฐฉ๋ฒ | const [state, setState] = useState(initialState) | const [state, dispatch] = useReducer(reducer, initialState) | | ์ฅ์ | ๊ตฌํ ๊ฐ๋จํ๊ณ ์ง๊ด์ | ๋ณต์กํ ์ํ ๋ก์ง ์ธ๋ถํ, ํ ์คํธ ์ฌ์, ์ํ ์ ๋ฐ์ดํธ ๋ก์ง ์ปดํฌ๋ํธ ์ธ๋ถ๋ก ๋ถ๋ฆฌ ๊ฐ๋ฅ | | ๋จ์ | ๋ณต์กํ ์ํ ๋ก์ง ๋ด๋ถ ํฌํจ์ํค๋ฉด ์ปดํฌ๋ํธ ๋น๋ํด์ง ์ ์์ | ์ฌ์ฉ๋ฒ useState๋ณด๋ค ๋ณต์ก, ์ด๊ธฐ ์ค์ ๋ง์ด ํ์ํ ์ ์์ | | ์ํ ์ ๋ฐ์ดํธ ๋ก์ง | ์ํ ์ ๋ฐ์ดํธ ์ํด ์๋ก์ด ์ํ ๊ฐ ์ง์ ์ค์ | ์ก์ ๊ฐ์ฒด ์ ์ํ๊ณ , ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฆฌ๋์ ํจ์ ํตํด ์ํ ์ ๋ฐ์ดํธ | | ์ ํฉํ ์ฌ์ฉ ์ฌ๋ก | ๋จ์ํ ์ํ ์ ๋ฐ์ดํธ, ์: ์นด์ดํฐ, ํ ๊ธ ์ค์์น | ์ํ ์ ๋ฐ์ดํธ ์ฌ๋ฌ ๋จ๊ณ์ ์กฐ๊ฑด ํฌํจํ๋ ๊ฒฝ์ฐ, ์: ์ผํ ์นดํธ, ๊ฒ์ ๋ก์ง |
๋ฒ์ธ
๊ฒ์ผ๋ฅธ ์ด๊ธฐํ (Lazy Initialization)
๊ฒ์ผ๋ฅธ ์ด๊ธฐํ๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ํ์ํ ๋๊น์ง ์ด๊ธฐํํ์ง ์๋ ํจํด์ ์๋ฏธํฉ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์ ์ฝํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํฐ ๋ฐ์ดํฐ ์ธํธ๋ ๊ณ์ฐ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ฐ์ ์ํ๋ก ๊ด๋ฆฌํด์ผ ํ ๋, ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋๊ฐ ์๋๋ผ ํด๋น ๊ฐ์ด ์ค์ ๋ก ํ์ํ ๋ ์ด๊ธฐํํ๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
React์์๋ useState ํ ์ ์ฌ์ฉํ ๋ ์ด๊ธฐ ์ํ๋ฅผ ํจ์๋ก ์ ๋ฌํจ์ผ๋ก์จ ๊ฒ์ผ๋ฅธ ์ด๊ธฐํ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ์ด ํจ์๋ ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋ ๋ ํ ๋ฒ๋ง ํธ์ถ๋๋ฉฐ, ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ด ์ด๊ธฐ ์ํ๊ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
์ด ๋ฐฉ๋ฒ์ ๋ฆฌ์์ค ์ฌ์ฉ์ ์ต์ ํํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์๊ฐ์ ๋จ์ถ์ํค๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
const [state, setState] = useState(() => {
// ์ด๊ธฐ ์ํ๋ฅผ ๊ณ์ฐํ๋ ๋ก์ง
const initialState = performExpensiveCalculation();
return initialState;
});
useReducer
useReducer๋ React์์ ๋ณต์กํ ์ํ ๋ก์ง์ ๊ด๋ฆฌํ ์ ์๋๋ก ๋์์ฃผ๋ ํ ์ ๋๋ค.
useState๋ณด๋ค ๋ ์ธ๋ฐํ ์ํ ๊ด๋ฆฌ๊ฐ ํ์ํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. useReducer๋ ํ์ฌ ์ํ์ ์ก์ ์ ์ธ์๋ก ๋ฐ๋ ๋ฆฌ๋์(reducer) ํจ์์, ์ด ๋ฆฌ๋์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ ๋ ๋ฐ์ํ ์ก์ ์ ์ ์ํ๋ ์ด๊ธฐ ์ํ๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
</>
);
}
useReducer๋ ์ํ ์ ๋ฐ์ดํธ ๋ก์ง์ ์ปดํฌ๋ํธ ๋ฐ๊นฅ์ผ๋ก ๋ถ๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๋ฉฐ, ์ก์ ์ ํตํด ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐฉ์์ Redux์ ์ ์ฌํ ํจํด์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
useReducer์ ๊ฒ์ผ๋ฅธ ์ด๊ธฐํ๋ฅผ ํจ๊ป ์ฌ์ฉํ ์๋ ์์ต๋๋ค. useReducer์ ๋ ๋ฒ์งธ ์ธ์๋ก ์ด๊ธฐ ์ํ๋ฅผ ๊ณ์ฐํ๋ ํจ์๋ฅผ ์ ๋ฌํจ์ผ๋ก์จ, ๋ณต์กํ ์ํ ๋ก์ง์ ๊ฐ์ง ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์์ต๋๋ค.
const [state, dispatch] = useReducer(reducer, initialArg, init);
์ฌ๊ธฐ์ initialArg๋ init ํจ์์ ์ ๋ฌ๋๋ฉฐ, init ํจ์๋ ์ด๊ธฐ ์ํ๋ฅผ ๊ณ์ฐํ์ฌ ๋ฐํํฉ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.