๊ธฐ๋ฅ ์ ์์ฒญํ๊ฑฐ๋ ๋ฒ๊ทธ๋ฅผ ๋ณด๊ณ ํ์๊ฒ ์ต๋๊น?
๋ฒ๋
ํ์ฌ ํ๋์ ๋ฌด์์ ๋๊น?
React.memo์์ ๋ถํ์ํ ๋ค์ ๋ ๋๋ง์ ๋ฐฉ์งํ๊ธฐ ์ํด (useContext ํํฌ)๋ฅผ ์ฌ์ฉํ์ฌ ์ปจํ ์คํธ API์ ๋ฐ์ดํฐ์ ์์กดํ ์ ์์ต๋๋ค.
ํ์ฌ ๋์์ด ๋ฒ๊ทธ์ธ ๊ฒฝ์ฐ ์ฌํ ๋จ๊ณ์ ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๋ฌธ์ ์ ์ต์ ๋ฐ๋ชจ๋ฅผ ์ ๊ณตํ์ญ์์ค. ์๋์ JSFiddle(https://jsfiddle.net/Luktwrdm/) ๋๋ CodeSandbox(https://codesandbox.io/s/new) ์์ ์ ๋ํ ๋งํฌ๋ฅผ ๋ถ์ฌ๋ฃ์ต๋๋ค.
React.memo(() => {
const [globalState] = useContext(SomeContext);
render ...
}, (prevProps, nextProps) => {
// How to rely on context in here?
// I need to rerender component only if globalState contains nextProps.value
});
์์๋๋ ๋์์ ๋ฌด์์ ๋๊น?
๋ ๋๋ง์ ๋ฐฉ์งํ๋ ค๋ฉด React.memo ๋ ๋ฒ์งธ ์ธ์ ์ฝ๋ฐฑ์ ์ปจํ
์คํธ์ ์ด๋ป๊ฒ๋ ์ก์ธ์คํด์ผ ํฉ๋๋ค.
๋๋ ํจ์ ๋ณธ๋ฌธ์์ ๋ฐ์ ๊ตฌ์ฑ ์์์ ์ด์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ ๊ฐ๋ฅ์ฑ์ด ์์ด์ผ ํฉ๋๋ค.
์ด๋ค ๋ฒ์ ์ React์ ์ด๋ค ๋ธ๋ผ์ฐ์ /OS๊ฐ ์ด ๋ฌธ์ ์ ์ํฅ์ ๋ฐ๋์?
16.8.4
์ด๊ฒ์ ์ค๊ณ๋ ๋๋ก ์๋ํฉ๋๋ค. ๊ถ๊ธํ ์ ์ด ์์ผ๋ฉด https://github.com/facebook/react/issues/14110 ์ ์ด์ ๋ํ ๋ ๊ธด ํ ๋ก ์ด ์์ต๋๋ค.
์ด๋ค ์ด์ ๋ก ๊ฐ์ theme
์์ฑ์ด ์๋ AppContext
๊ฐ ์๊ณ appContextValue.theme
๋ณ๊ฒฝ ์ ์ผ๋ถ ExpensiveTree
๋ง ๋ค์ ๋ ๋๋งํ๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
TLDR์ ํ์ฌ๋ก์๋ ์ธ ๊ฐ์ง ์ต์ ์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ง์ ๊ตฌ์ฑ ์์์์ appContextValue.theme
๊ฐ ํ์ํ์ง๋ง appContextValue
์์ฒด๊ฐ ๋๋ฌด ์์ฃผ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ThemeContext
์์ AppContext
ThemeContext
๋ฅผ ๋ถํ ํ ์ ์์ต๋๋ค.
function Button() {
let theme = useContext(ThemeContext);
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}
์ด์ AppContext
๋ณ๊ฒฝํด๋ ThemeContext
์๋น์๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ต๋๋ค.
์ด๊ฒ์ ์ ํธ๋๋ ์์ ์ฌํญ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ํน๋ณํ ๊ตฌ์ ๊ธ์ต์ด ํ์ํ์ง ์์ต๋๋ค.
memo
๋ฅผ ๋ฃ์ต๋๋ค.์ด๋ค ์ด์ ๋ก ์ปจํ ์คํธ๋ฅผ ๋ถํ ํ ์ ์๋ ๊ฒฝ์ฐ์๋ ๊ตฌ์ฑ ์์๋ฅผ ๋๋ก ๋ถํ ํ๊ณ ๋ด๋ถ ๊ตฌ์ฑ ์์์ ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ props๋ฅผ ์ ๋ฌํ์ฌ ๋ ๋๋ง์ ์ต์ ํํ ์ ์์ต๋๋ค. ๋น์ ์ ์ฌ์ ํ โโ๋ฐ๊นฅ ์ชฝ์ ๋ ๋๋งํ์ง๋ง ์๋ฌด ๊ฒ๋ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ ๋ ดํด์ผํฉ๋๋ค.
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return <ThemedButton theme={theme} />
}
const ThemedButton = memo(({ theme }) => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
});
useMemo
๊ตฌ์ฑ์์ 1๊ฐ๋ง์ง๋ง์ผ๋ก ์ฝ๋๋ฅผ ์ข ๋ ์ฅํฉํ๊ฒ ๋ง๋ค ์ ์์ง๋ง ๋ฐํ ๊ฐ์ useMemo
๋ก ๋ํํ๊ณ ์ข
์์ฑ์ ์ง์ ํ์ฌ ๋จ์ผ ๊ตฌ์ฑ ์์์ ์ ์งํ ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๋ ์ฌ์ ํ ์ฌ์คํ๋์ง๋ง ๋ชจ๋ useMemo
์
๋ ฅ์ด ๋์ผํ ๊ฒฝ์ฐ React๋ ์์ ํธ๋ฆฌ๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ต๋๋ค.
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return useMemo(() => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}, [theme])
}
์์ผ๋ก ๋ ๋ง์ ์๋ฃจ์ ์ด ์์ ์ ์์ง๋ง ์ด๊ฒ์ด ํ์ฌ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ ๋๋ค.
๊ทธ๋๋ ์ต์ 1์ด ๋ ์ข์ต๋๋ค. ์ผ๋ถ ์ปจํ ์คํธ๊ฐ ๋๋ฌด ์์ฃผ ๋ณ๊ฒฝ๋๋ฉด ๋ถํ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
ํ ๋ง๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒฝ์ฐ ์ด ๋ ์ต์ ๋ชจ๋ ์์ ๋ ๋๋ง์์ ์ ์ธ๋ฉ๋๋ค.
@gaearon ๋ฒํผ์ด ์์์ ๋๊น ์๋๋ฉด ๋ฒํผ์ด ์์์ ๋ ๋๋งํฉ๋๊น? ์ด๊ฒ๋ค์ด ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง ์ปจํ ์คํธ๊ฐ ๋๋ฝ๋์์ต๋๋ค.
unstable_Profiler
์ต์
2๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ ํ onRender
์ฝ๋ฐฑ์ ํธ๋ฆฌ๊ฑฐํ์ง๋ง ์ค์ ๋ ๋๋ง ๋ก์ง์ ํธ์ถํ์ง ์์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ ์๋ชปํ๊ณ ์๋ ๊ฑด ์๋๊น? ~ https://codesandbox.io/s/kxz4o2oyoo~ https://codesandbox.io/s/00yn9yqzjw
์์ ๋ฅผ ๋ ๋ช ํํ๊ฒ ์ ๋ฐ์ดํธํ์ต๋๋ค.
๋ถ์์ ํ_ํ๋กํ์ผ๋ฌ ์ต์ 2๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ์ ํ onRender ์ฝ๋ฐฑ์ ํธ๋ฆฌ๊ฑฐํ์ง๋ง ์ค์ ๋ ๋๋ง ๋ก์ง์ ํธ์ถํ์ง ์์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ ์๋ชปํ๊ณ ์๋ ๊ฑด ์๋๊น? https://codesandbox.io/s/kxz4o2oyoo
๊ทธ๊ฒ์ด ๋ฐ๋ก ๊ทธ ์ต์ ์ ์์ ์ ๋๋ค. :-)
์๋ง๋ ์ด์ ๋ํ ์ข์ ํด๊ฒฐ์ฑ
์ ์ฃผ์ด์ง ์ฝ๋ฐฑ์ด true๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ์๋ง ์ปจํ
์คํธ๋ฅผ "๊ฐ์ ธ๊ฐ" ๊ตฌ์ฑ ์์๋ฅผ ๋ค์ ๋ ๋๋งํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ ๊ฐ๋ ๊ฒ์
๋๋ค. ์:
useContext(ThemeContext, (contextData => contextData.someArray.length !== 0 ));
์ค์ ๋ก ๋ง๋ ํํฌ์ ์ฃผ์ ๋ฌธ์ ๋ ํํฌ ๋ด๋ถ์์ ๊ตฌ์ฑ ์์๊ฐ ๋ฐํํ๋ ๊ฒ์ ๊ด๋ฆฌํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ ๋๋ง์ ๋ฐฉ์งํ๊ณ ๋ฉ๋ชจํ๋ ๊ฐ์ ๋ฐํํ๋ ๋ฑ์ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ค๋ฉด, ๊ทธ๊ฒ์ ๊ตฌ์ฑํ ์ ์์ ๊ฒ์ ๋๋ค.
https://overreacted.io/why-isnt-xa-hook/#not -a-hook-usebailout
์ต์ 4: ๋ฐ์ดํฐ ์ ํ์ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ์ง ๋ง๊ณ ๋ฐ์ดํฐ ๊ตฌ๋ ์ ์ฌ์ฉํ์ญ์์ค. useSubscription์ ์ฌ์ฉํ์ญ์์ค(๋ชจ๋ ๊ฒฝ์ฐ๋ฅผ ์ปค๋ฒํ๊ธฐ ์ํด ์์ฑํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์).
๋ค์ ๋ ๋๋ง์ ๋ฐฉ์งํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
"์ฌ๋ ๋๋ง ๊ตฌ์ฑ ์์์์ JSX๋ฅผ ํ ๋จ๊ณ ์๋ก ์ด๋ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋งค๋ฒ ๋ค์ ์์ฑ๋์ง ์์ต๋๋ค."
์๋ง๋ ์ด์ ๋ํ ์ข์ ํด๊ฒฐ์ฑ ์ ์ฃผ์ด์ง ์ฝ๋ฐฑ์ด true๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ์๋ง ์ปจํ ์คํธ๋ฅผ "๊ฐ์ ธ๊ฐ" ๊ตฌ์ฑ ์์๋ฅผ ๋ค์ ๋ ๋๋งํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ ๊ฐ๋ ๊ฒ์ ๋๋ค. ์:
useContext(ThemeContext, (contextData => contextData.someArray.length !== 0 ));
์ค์ ๋ก ๋ง๋ ํํฌ์ ์ฃผ์ ๋ฌธ์ ๋ ํํฌ ๋ด๋ถ์์ ๊ตฌ์ฑ ์์๊ฐ ๋ฐํํ๋ ๊ฒ์ ๊ด๋ฆฌํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ ๋๋ง์ ๋ฐฉ์งํ๊ณ ๋ฉ๋ชจํ๋ ๊ฐ์ ๋ฐํํ๋ ๋ฑ์ ๋๋ค.
์ฌ๊ธฐ์์ ์ฐธ/๊ฑฐ์ง ๋์ ... ์ปจํ ์คํธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ถ์งํฉํ ์ ์๋ ID ๊ธฐ๋ฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ ์ ์์ต๋๊น?
const contextDataINeed = useContext(ContextObj, (state) => state['keyICareAbout'])
์ฌ๊ธฐ์ useContext๋ ์ ํ๊ธฐ fn์ ๊ฒฐ๊ณผ๊ฐ ๋์ผํ ํจ์์ ์ด์ ๊ฒฐ๊ณผ์ ๋์ผํ์ง ์๋ ํ ์ด ๊ตฌ์ฑ ์์์์ ํ์ ๋์ง ์์ต๋๋ค.
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Facebook์ด ํํฌ์ ํตํฉํ๋ ์๋ฃจ์ ์ผ ์ ์์์ ๋ฐ๊ฒฌํ์ต๋๋ค. https://blog.axlight.com/posts/super-performant-global-state-with-react-context-and-hooks/
๋ค์ ๋ ๋๋ง์ ๋ฐฉ์งํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
"์ฌ๋ ๋๋ง ๊ตฌ์ฑ ์์์์ JSX๋ฅผ ํ ๋จ๊ณ ์๋ก ์ด๋ํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋งค๋ฒ ๋ค์ ์์ฑ๋์ง ์์ต๋๋ค."
๋ฌธ์ ๋ ์์์ ์๋๋ก ๋ค์ ๋ ๋๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ตฌ์ฑ ์์ ํธ๋ฆฌ๋ฅผ ์ฌ๊ตฌ์ฑํ๋ ๋ฐ ๋น์ฉ์ด ๋ง์ด ๋ค ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
@fuleinist ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ๋ง์ด ๋จ์ํ๋์์ง๋ง ๊ถ๊ทน์ ์ผ๋ก MobX์ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ต๋๋ค. MobX๋ ์ด๋ฏธ ์ด์ ๊ฐ์ด ์๋ํ๊ณ (ํ๋ก์๋ ์ฌ์ฉ) ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ณ ์ํ์ ํน์ ๋นํธ๋ฅผ ์ฌ์ฉํ๋ ๊ตฌ์ฑ ์์๊ฐ ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค.
@gaearon ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์น๊ณ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง ๋ ๋ฒ์งธ ๋ฐ ์ธ ๋ฒ์งธ ์ต์ ์ ์๋ํ์ง๋ง ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง ์์ต๋๋ค. ์ด๊ฒ์ด ํฌ๋กฌ ํ์ฅ ๋ฒ๊ทธ์ ๋ฐ์ํ๋์ง ์๋๋ฉด ๋ค๋ฅธ ์บ์น๊ฐ ์๋์ง ํ์คํ์ง ์์ต๋๋ค. ๋ค์์ ๋ ์ ๋ ฅ์ ๋ชจ๋ ๋ค์ ๋ ๋๋งํ๋ ํ์์ ๊ฐ๋จํ ์์ ๋๋ค. ์ฝ์์์ ๋ฉ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง DOM์ ํญ์ ๋ค์ ๋ ๋๋ง๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. 1000๊ฐ ํญ๋ชฉ์ ์๋ํ๋๋ฐ onChange ์ด๋ฒคํธ๊ฐ ์ ๋ง ๋๋ ค์ memo()๊ฐ ์ปจํ ์คํธ์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์กฐ์ธ ๊ฐ์ฌํฉ๋๋ค:
๋ค์์ 1000๊ฐ ํญ๋ชฉ/ํ ์คํธ ์์๊ฐ ์๋ ๋ฐ๋ชจ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ ๋ฐ๋ชจ์์ ๊ฐ๋ฐ ๋๊ตฌ๋ ๋ค์ ๋ ๋๋ง์ ํ์ํ์ง ์์ต๋๋ค. ํ ์คํธํ๋ ค๋ฉด ๋ก์ปฌ์์ ์์ค๋ฅผ ๋ค์ด๋ก๋ํด์ผ ํฉ๋๋ค. https://codesandbox.io/embed/zen-firefly-d5bxk
import React, { createContext, useState, useContext, memo } from "react";
const FormContext = createContext();
const FormProvider = ({ initialValues, children }) => {
const [values, setValues] = useState(initialValues);
const value = {
values,
setValues
};
return <FormContext.Provider value={value}>{children}</FormContext.Provider>;
};
const TextField = memo(
({ name, value, setValues }) => {
console.log(name);
return (
<input
type="text"
value={value}
onChange={e => {
e.persist();
setValues(prev => ({
...prev,
[name]: e.target.value
}));
}}
/>
);
},
(prev, next) => prev.value === next.value
);
const Field = ({ name }) => {
const { values, setValues } = useContext(FormContext);
const value = values[name];
return <TextField name={name} value={value} setValues={setValues} />;
};
const App = () => (
<FormProvider initialValues={{ firstName: "Marr", lastName: "Keri" }}>
First name: <Field name="firstName" />
<br />
Last name: <Field name="lastName" />
</FormProvider>
);
export default App;
๋ฐ๋ฉด์ ์ปจํ ์คํธ๊ฐ ์๋ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง๋ง ๋๋ฒ๊ทธ์์๋ ์ฌ์ ํ ์์๋ณด๋ค ๋๋ฆฌ์ง๋ง ์ ์ด๋ ๋ค์ ๋ ๋๋งํ๋ ๊ฒ์ ๊ด์ฐฎ์ต๋๋ค.
import React, { useState, memo } from "react";
import ReactDOM from "react-dom";
const arr = [...Array(1000).keys()];
const TextField = memo(
({ index, value, onChange }) => (
<input
type="text"
value={value}
onChange={e => {
console.log(index);
onChange(index, e.target.value);
}}
/>
),
(prev, next) => prev.value === next.value
);
const App = () => {
const [state, setState] = useState(arr.map(x => ({ name: x })));
const onChange = (index, value) =>
setState(prev => {
return prev.map((item, i) => {
if (i === index) return { name: value };
return item;
});
});
return state.map((item, i) => (
<div key={i}>
<TextField index={i} value={item.name} onChange={onChange} />
</div>
));
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
@marrkeri ์ฒซ ๋ฒ์งธ ์ฝ๋ ์กฐ๊ฐ์์ ์๋ชป๋ ๊ฒ์ด ๋ณด์ด์ง ์์ต๋๋ค. dev ๋๊ตฌ์์ ๊ฐ์กฐ ํ์๋ ๊ตฌ์ฑ ์์๋ ์ปจํ
์คํธ๋ฅผ ์ฌ์ฉํ๋ Field
์ด๋ฉฐ ๋ฉ๋ชจ ๊ตฌ์ฑ ์์์ด๋ฉฐ areEqual ๊ธฐ๋ฅ์ ๊ตฌํํ๋ TextField
๊ฐ ์๋๋๋ค.
์ฝ๋์๋๋ฐ์ค ์์ ์ ์ฑ๋ฅ ๋ฌธ์ ๋ ์ปจํ
์คํธ๋ฅผ ์ฌ์ฉํ๋ 1000๊ฐ์ ๊ตฌ์ฑ ์์์์ ๋น๋กฏ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ปจํ
์คํธ๋ฅผ ์ฌ์ฉํ๋ ํ๋์ ๊ตฌ์ฑ ์์(์ Fields
๋ฆฌํฉํฐ๋งํ๊ณ ํด๋น ๊ตฌ์ฑ ์์(๋งต ํฌํจ)์์ ๊ฐ ๊ฐ์ ๋ํด TextField
๋ฅผ ๋ฐํํฉ๋๋ค.
@marrkeri ์ฒซ ๋ฒ์งธ ์ฝ๋ ์กฐ๊ฐ์์ ์๋ชป๋ ๊ฒ์ด ๋ณด์ด์ง ์์ต๋๋ค. dev ๋๊ตฌ์์ ๊ฐ์กฐ ํ์๋ ๊ตฌ์ฑ ์์๋ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋
Field
์ด๋ฉฐ ๋ฉ๋ชจ ๊ตฌ์ฑ ์์์ด๋ฉฐ areEqual ๊ธฐ๋ฅ์ ๊ตฌํํ๋TextField
๊ฐ ์๋๋๋ค.์ฝ๋์๋๋ฐ์ค ์์ ์ ์ฑ๋ฅ ๋ฌธ์ ๋ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋ 1000๊ฐ์ ๊ตฌ์ฑ ์์์์ ๋น๋กฏ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋ ํ๋์ ๊ตฌ์ฑ ์์(์
Fields
๋ฆฌํฉํฐ๋งํ๊ณ ํด๋น ๊ตฌ์ฑ ์์(๋งต ํฌํจ)์์ ๊ฐ ๊ฐ์ ๋ํดTextField
๋ฅผ ๋ฐํํฉ๋๋ค.
๋น์ ์ด ๋งํ๋ฏ์ด ๋๋ ๊ฐ์ ์๊ฐ ์๋์ ์์๋ค
ํ๋์ ๊ตฌ์ฑ ์์๋ก ๋ฆฌํฉํ ๋งํ๋ ๊ฒ์ ๋ํ ๋ ๋ฒ์งธ ์์ ์ ํ์
ํ์ง ๋ชปํ์ต๋๋ค.
@marrkeri ์ ๋ https://codesandbox.io/s/little-night-p985y ์ ๊ฐ์ ๊ฒ์ ์ ์ํ์ต๋๋ค
์ด๊ฒ์ด react-redux๊ฐ ์์ ์ ์ธ ์ปจํ ์คํธ API์ ์ด์ ์ ์ฌ์ฉ ํ์ง ์๊ณ Hooks๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ ๋ ์ปจํ ์คํธ์ ํ์ฌ ์ํ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์
๊ทธ๋์ ์๋ ๊ฒ ๊ฐ๋ค.
์ฌ์ฉ๋ฒ์ ์ ์ดํ์ง ์๊ณ (์ต์ 2-3์ ํ์) ๊ฐ๋ฅํ ๋ชจ๋ ์ ํ๊ธฐ๋ฅผ ์ด๊ฑฐํ ์ ์์ง๋ง(์ต์ 1์ ํ์) Hooks API๋ฅผ ๋ ธ์ถํ๋ ค๋ ๊ฒฝ์ฐ ์ ์ผํ ์ต์ ์ผ ์ ์์ต๋๋ค.
const MyContext = createContext()
export const Provider = ({children}) => (
<MyContext.provider value={{subscribe: listener => ..., getValue: () => ...}}>
{children}
</MyContext.provider>
)
export const useSelector = (selector, equalityFunction = (a, b) => a === b) => {
const {subscribe, getValue} = useContext(MyContext)
const [value, setValue] = useState(getValue())
useEffect(() => subscribe(state => {
const newValue = selector(state)
if (!equalityFunction(newValue, value) {
setValue(newValue)
}
}), [selector, equalityFunction])
}
@Hypnosphi : ์ฐ๋ฆฌ๋ ์ปจํ ์คํธ(v6 ๊ตฌํ)์์ ์คํ ์ด ์ํ ์ ๋ฌ์ ์ค๋จํ๊ณ ์ง์ ์คํ ์ด ๊ตฌ๋ (v7 ๊ตฌํ)์ผ๋ก ๋ค์ ์ ํํ์ต๋๋ค. ์ฑ๋ฅ ๋ฌธ์ ์ ์ปจํ ์คํธ๋ก ์ธํ ์ ๋ฐ์ดํธ๋ฅผ ๊ตฌ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. v6 ์ ๊ทผ ๋ฐฉ์์ ๊ธฐ๋ฐ์ผ๋ก React-Redux ํํฌ API๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค).
์์ธํ ๋ด์ฉ์ ๋ด ํฌ์คํธ React-Redux์ ์ญ์ฌ ๋ฐ ๊ตฌํ์ ์ฐธ์กฐํ์ญ์์ค.
์ค๋ ๋๋ฅผ ์ฝ์์ง๋ง ์ฌ์ ํ ๊ถ๊ธํ ์ ์ด ์์ต๋๋ค. ์์ ๋์ด๋ "์ต์ 1 2 3 4" ์ปจํ ์คํธ ๋ณ๊ฒฝ ์ ์กฐ๊ฑด๋ถ๋ก ๋ค์ ๋ ๋๋งํ ์ ์๋ ์ ์ผํ ์ต์ ์ด ์ค๋ ์์ต๋๊น? ๊ณต์์ ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ค๋ฅธ ์์ ์ด ์งํ ์ค์ด๊ฑฐ๋ "4๊ฐ์ง ์๋ฃจ์ "์ด ์ถฉ๋ถํ ์์ฉ ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๊น?
๋๋ ๋ค๋ฅธ ์ค๋ ๋์ ์ผ์ง๋ง ๋ง์ผ์ ์ํด. ๋ค์์ _๋น๊ณต์์ ์ธ_ ํด๊ฒฐ ๋ฐฉ๋ฒ์
๋๋ค.
userland์ useContextSelector ์ ์ ๋ฐ use-context-selector ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
์์งํ ์ด๊ฒ์ ํ๋ ์์ํฌ๊ฐ ์ฐ๋ฆฌ๊ฐ ๊ถ์ฅํ๋ ๊ฒ์ฒ๋ผ ๊ธฐ๋ฅ๊ณผ ํํฌ์ ์์ ํ ๋ค์ด๊ฐ ์ค๋น๊ฐ ๋์ง ์์๋ค๊ณ ์๊ฐํ๊ฒ ๋ง๋ญ๋๋ค. ํด๋์ค์ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๊ฒ๋ค์ ๊น๋ํ๊ฒ ์ ์ดํ ์ ์์๊ณ ์ด์ ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ฌ ๋ ์ฝ๊ธฐ ์ด๋ ค์ด ๊ตฌ๋ฌธ์ด ๋ฉ๋๋ค.
์ต์ 3์ด ์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด๊ฐ ์๋ชปํ๊ณ ์์ต๋๊น? https://stackblitz.com/edit/react-w8gr8z
@Martin , ๋๋ ๊ทธ๊ฒ์ ๋์ํ์ง ์์ต๋๋ค.
ํํฌ ํจํด์ ์ ๊ตฌ์ฑ๋ ๋ฌธ์์ ์ฝ๋๋ก ์ฝ์ ์ ์์ต๋๋ค.
๊ตฌ์กฐ ๋ฐ React ํด๋์ค ๋ฐ ์๋ช
์ฃผ๊ธฐ๋ ๋ชจ๋ ๊ธฐ๋ฅ์ผ๋ก ๋์ฒด ๊ฐ๋ฅํฉ๋๋ค.
๋๋ฑํ ๊ฒ.
๋ถํํ๋ ๋ฐ์ ํจํด์ ๋ค์์ ํตํด React๋ก ๋ฌ์ฑํ ์ ์์ต๋๋ค.
React ํด๋์ค ๋๋ ํํฌ.
2020๋
1์ 11์ผ ํ ์์ผ ์ค์ 9์ 44๋ถ Martin Genev [email protected]
์ผ๋ค:
์์งํ ์ด๊ฒ์ ํ๋ ์์ํฌ๊ฐ ์์ง ์ค๋น๋์ง ์์๋ค๊ณ ์๊ฐํ๊ฒ ๋ง๋ญ๋๋ค.
์ฐ๋ฆฌ๊ฐ ๊ถ์ฅํ๋ ๊ฒ์ฒ๋ผ ์์ ํ ๊ธฐ๋ฅ๊ณผ ํํฌ์. ์์ ๊ณผ ํจ๊ป
์ด๋ฌํ ๊ฒ๋ค์ ๊น๋ํ๊ฒ ์ ์ดํ ์ ์๋ ๋ผ์ดํ์ฌ์ดํด ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค.
์ด์ ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ฌ ๋ ์ฝ๊ธฐ ์ด๋ ค์ด ๊ตฌ๋ฌธ์ด ๋ฉ๋๋ค.โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธํ์ธ์.
https://github.com/facebook/react/issues/15156?email_source=notifications&email_token=AAI4DWUJ7WUXMHAR6F2KVXTQ5D25TA5CNFSM4G7UEEO2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63
๋๋ ๊ตฌ๋ ์ทจ์
https://github.com/notifications/unsubscribe-auth/AAI4DWUCO7ORHV5OSDCE35TQ5D25TANCNFSM4G7UEEOQ
.
@mgenev ์ต์
3์ ์์์ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํฉ๋๋ค( <ExpensiveTree />
, ์ด๋ฆ ์์ฒด๊ฐ ๋งํจ)
@Hypnosphi ๊ฐ์ฌํฉ๋๋ค, ๋ง์ต๋๋ค.
https://stackblitz.com/edit/react-ycfyye
๋ค์ ์์ฑํ๊ณ ์ด์ ์ค์ ๋ ๋๋ง(๋์คํ๋ ์ด) ๊ตฌ์ฑ ์์๊ฐ ๋ค์ ๋ ๋๋ง๋์ง ์์ง๋ง ๋ชจ๋ ์ปจํ ์ด๋(์ฐ๊ฒฐ๋ ์ปจํ ์คํธ)๋ ์ฌ์ฉ ์ค์ธ์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด ์ปจํ ์คํธ์์ prop์ด ๋ณ๊ฒฝ๋ ๋ ๋ ๋๋ง๋ฉ๋๋ค. ์ด์ ๋ด๊ฐ ๋ณผ ์ ์๋ ์ ์ผํ ์ต์ ์ ์ปจํ ์คํธ ๋ถํ ์ ์์ํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ถ ํญ๋ชฉ์ ์ง์ ์ผ๋ก ์ ์ญ์ ์ด๋ฉฐ ์ต๊ณ ์์ค์์ ๋ํ๋๋ฉฐ ๊ทธ ์์ ์ํ์ ๋ณ๊ฒฝํ๋ฉด ์ ์ฒด ์ฑ์์ ๋ชจ๋ ์ปจํ ์ด๋๊ฐ ์คํ๋ฉ๋๋ค. ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ์ฑ๋ฅ์ ์ข์ ์ ์๋์ง ์ดํดํ์ง ๋ง์ญ์์ค ...
์ฑ๋ฅ์ ์ผ๋ก ์ด๊ฒ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ข์ ์๊ฐ ์ด๋์ ์์ต๋๊น? ๊ณต์ ๋ฌธ์๋ ์ ๋ง ์ ํ์ ์ ๋๋ค
๊ธฐ๋ณธ์ ์ผ๋ก react-redux๊ฐ ๋ด๋ถ์ ์ผ๋ก ์ํํ๋ ์ต์
4๋ฅผ ์๋ํด ๋ณผ ์ ์์ต๋๋ค.
https://github.com/facebook/react/issues/15156#issuecomment -546703046
subscribe
๊ธฐ๋ฅ์ ๊ตฌํํ๋ ค๋ฉด Observables ๋๋ EventEmitter์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๊ฑฐ๋ ๊ธฐ๋ณธ ๊ตฌ๋
๋ก์ง์ ์ง์ ์์ฑํ ์ ์์ต๋๋ค.
function StateProvider({children}) {
const [state, dispatch] = useReducer(reducer, initialState)
const listeners = useRef([])
const subscribe = listener => {
listeners.current.push(listener)
}
useEffect(() => {
listeners.current.forEach(listener => listener(state)
}, [state])
return (
<DispatchContext.Provider value={dispatch}>
<SubscribeContext.Provider value={{subscribe, getValue: () => state}}>
{children}
</SubscribeContext.Provider>
</DispatchContext.Provider>
);
}
๊ด์ฌ์ด ์๋ ์ฌ๋๋ค์ ์ํด ์ด ์ฃผ์ ์ ๋ค์ ๊ด๋ จ์ด ์๋ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋น๊ตํฉ๋๋ค.
https://github.com/dai-shi/will-this-react-global-state-work-in-concurrent-mode
๋์ ์ต๊ทผ ๋
ธ๋ ฅ์ ๋ค๊ฐ์ค๋ ๋์ ๋ชจ๋์์ ์ค์ํ useTransition
๋ก ์ํ ๋ถ๊ธฐ ์ง์์ ํ์ธํ๋ ๊ฒ์
๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก React ์ํ์ ์ปจํ
์คํธ๋ฅผ ์ ์์ ์ผ๋ก ์ฌ์ฉํ๋ฉด OK์
๋๋ค. (๊ทธ๋ ์ง ์์ผ๋ฉด this ์
๊ฐ์ฌํฉ๋๋ค @dai-shi ๊ทํ์ ํจํค์ง๊ฐ ์ ๋ง ๋ง์์ ๋ค๊ณ ์ฑํํ๋ ค๊ณ ํฉ๋๋ค.
@dai-shi ์๋
ํ์ธ์, ๋ฐฉ๊ธ react-tracked
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๊ณ ์ฝ์๋๋ก ์ปจํ
์คํธ์ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด ์ ๋ง ์ข์ ๋ณด์
๋๋ค. ์ฌ์ ํ ์ค์ ์ ์ด๊ฑฐ๋ ๋ค๋ฅธ ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๊น? ์ฌ๊ธฐ์ use-reducer-async
https://github.com/dai-shi/react-tracked/blob/master/examples/12_async/src/store๋ก ๋ฏธ๋ค์จ์ด ์์ค์ ๋ง๋๋ ๋ฐฉ๋ฒ๋ ๋ณด์ฌ์ค๋๋ค. useReducer
์ฌ์ฉํ์ฌ ๋น์ทํ ์์
์ ์ํํ์ผ๋ฉฐ ๋น๋๊ธฐ ๋ฏธ๋ค์จ์ด์ฉ์ผ๋ก dispatch
๋ฅผ ๋ด ๊ฒ์ผ๋ก ๋ํํ๊ณ Context
ํ์ง๋ง ์ปจํ
์คํธ ๋ํ์ผ๋ก ์ธํด ํฅํ ๋ ๋๋ง ์ฑ๋ฅ ๋ฌธ์ ์ ๋ํด ๊ฑฑ์ ํ๊ณ ์์ต๋๋ค.
@bobrosoft react-tracked
๋ ๊ฝค ์์ ์ ์
๋๋ค(ํ์คํ ํ๋์ ๊ฐ๋ฐ์ ์ ํ์ผ๋ก). ํผ๋๋ฐฑ์ ๋งค์ฐ ํ์ํ๋ฉฐ ๊ทธ๋ ๊ฒ ํ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ฐ์ ๋ ๊ฒ์
๋๋ค. ํ์ฌ ๋ด๋ถ์ ์ผ๋ก๋ ๋ฌธ์ํ๋์ง ์์ React์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ์์ผ๋ก ๋ ๋์ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก ๋์ฒดํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. use-reducer-async
๋ ๊ฑฐ์ ์๋ชป๋์ง ์๋ ๊ฐ๋จํ ๊ตฌ๋ฌธ ์คํ๊ณผ ๊ฐ์ต๋๋ค.
์ด HoC๋ ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค.
````
'๋ฐ์'์์ React, { useMemo, ReactElement, FC } ๊ฐ์ ธ์ค๊ธฐ;
'lodash/reduce'์์ ์์
๊ฐ์;
์ ํ ์ ํ๊ธฐ = (์ปจํ ์คํธ: ๋ชจ๋ ) => ๋ชจ๋ ;
์ธํฐํ์ด์ค ์ ํ๊ธฐ ๊ฐ์ฒด {
}
const withContext = (
๊ตฌ์ฑ ์์: FC,
์ปจํ
์คํธ: ๋ชจ๋ ,
์ ํ๊ธฐ: SelectorObject,
): FC => {
return (props: any): ReactElement => {
const ์๋น์ = ({ ์ปจํ
์คํธ }: ๋ชจ๋ ): ReactElement => {
const contextProps = ์ถ์(
์ ํ๊ธฐ,
(acc: any, selector: Selector, key: string): any => {
const ๊ฐ = ์ ํ๊ธฐ(์ปจํ
์คํธ);
acc[ํค] = ๊ฐ;
๋ฐํ acc;
},
{},
);
์ฌ์ฉ๋ฉ๋ชจ ๋ฐํ(
(): ReactElement =>
[...Object.values(props), ...Object.values(contextProps)],
);
};
๋ฐํ (
{(context: any): ReactElement =>
);
};
};
๊ธฐ๋ณธ ๋ด๋ณด๋ด๊ธฐ withContext;
````
์ฌ์ฉ ์:
export default withContext(Component, Context, {
value: (context): any => context.inputs.foo.value,
status: (context): any => context.inputs.foo.status,
});
์ด๊ฒ์ redux mapStateToProps์ ๋๋ฑํ ์ปจํ ์คํธ๋ก ๋ณผ ์ ์์ต๋๋ค.
redux์ connect()์ ๊ฑฐ์ ์ ์ฌํ ์์ ํญ๋ชฉ์ ๋ง๋ค์์ต๋๋ค.
const withContext = (
context = createContext(),
mapState,
mapDispatchers
) => WrapperComponent => {
function EnhancedComponent(props) {
const targetContext = useContext(context);
const { ...statePointers } = mapState(targetContext);
const { ...dispatchPointers } = mapDispatchers(targetContext);
return useMemo(
() => (
<WrapperComponent {...props} {...statePointers} {...dispatchPointers} />
),
[
...Object.values(statePointers),
...Object.values(props),
...Object.values(dispatchPointers)
]
);
}
return EnhancedComponent;
};
๊ตฌํ :
const mapActions = state => {
return {};
};
const mapState = state => {
return {
theme: (state && state.theme) || ""
};
};
export default connectContext(ThemeContext, mapState, mapActions)(Button);
์ ๋ฐ์ดํธ: ๊ถ๊ทน์ ์ผ๋ก ๋์ ๋ฆฌ์ค๋(๋ง์ฐ์ค ์ด๋ ์)๋ฅผ ์ฌ์ฉํ์ฌ ๋น ๋ฅด๊ฒ ๋ณํํ๋ ์ธ๋ถํ๋ ๋ฐ์ดํฐ๋ฅผ ์ํด EventEmitter๋ก ์ ํํ์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ์์ ์ ์ํ ๋ ๋์ ๋๊ตฌ๋ผ๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ์ปจํ ์คํธ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๋ ๋ฐ ์ ํฉํ์ง๋ง ์๋ก ๊ณ ์นจ ๋น๋๊ฐ ๋์ง๋ ์์ต๋๋ค.
์ปจํ ์คํธ๋ฅผ ์ ์ธ์ ์ผ๋ก ๊ตฌ๋ ํ๊ฑฐ๋ ๊ตฌ๋ ํ์ง ์๋ ๊ฒ์ด ์๋๊ฐ์? useContext()๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๊ตฌ์ฑ ์์์์ ๊ตฌ์ฑ ์์๋ฅผ ์กฐ๊ฑด๋ถ๋ก ๋ํํฉ๋๋ค.
์ฃผ์ ์๊ตฌ ์ฌํญ์ ๋ด๋ถ ๊ตฌ์ฑ ์์๊ฐ ์ํ๋ฅผ ๊ฐ์ง ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ถ๊ธฐ ๋๋ฌธ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฅธ ์ธ์คํด์ค๊ฐ ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ฏธ๋ฆฌ ๋ ๋๋งํ ๋ค์ cloneElement๋ฅผ ์ฌ์ฉํ์ฌ ์ํ์ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
์ผ๋ถ ๊ตฌ์ฑ ์์๋ ๋ ๋๋ง์ ์ปจํ
์คํธ์ ๊ด๋ จ์ด ์์ง๋ง "๊ฐ์ ์ฝ์ด์ผ" ํฉ๋๋ค. ๋ด๊ฐ ๋ฌด์์ ๋์น๊ณ ์์ต๋๊น?
Context._currentValue ๋ ํ๋ก๋์ ์์ ์ฌ์ฉํ๊ธฐ์ ์์ ํฉ๋๊น?
๊ฐ๋ฅํ ํ ์ ๋ ดํ๊ฒ ๋ ๋๋งํ ์ ์๋ ์ปจํ ์คํธ์ ๊ตฌ์ฑ ์์๋ฅผ ๊ตฌ๋ ํ๋ ค๊ณ ํฉ๋๋ค. ํ์ง๋ง ๊ทธ๋ฐ ๋ค์ ๋๋ ์๋ ๋ฐฉ์์ผ๋ก ์คํ๊ฒํฐ ์ฝ๋๋ก ์ํ์ ์ ๋ฌํ๊ฑฐ๋ ์ ๋ฐ์ดํธ์ ๋ ผ๋ฆฌ์ ์ธ ๊ฒ์ด ์์ ๋ ์ ๋ฐ์ดํธ ๊ตฌ๋ ์ ํผํ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋ฉ๋ชจ ์๋ฃจ์ ์ ๊ตฌ์ฑ ์์ ๋ ๋๋ง์ด ์ปจํ ์คํธ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง์ง๋ง ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ...
@vamshi9666 ๋ง์ด
https://recoiljs.org/ ์ด ๋ฌธ์ ์ ๋ํ ์ข์ ํด๊ฒฐ์ฑ ์ ์ฐพ์์ต๋๋ค. React์ ํตํฉํ๋ฉด ๊ต์ฅํ ๊ฒ ๊ฐ์์.
@vamshi9666 ๋ง์ด
ํ ๊ณณ์์๋ง ์ฌ์ฉํ์ผ๋ฉฐ ์ด๊ธฐ ๋ชฉํ๋ jsx์์ ์ํ ๊ด๋ฆฌ๋ฅผ ๋ถ๋ฆฌํ์ง๋ง ์์ฉ๊ตฌ๋ฅผ ๋ง๋ค์ง ์๋ ๊ฒ์ ๋๋ค. ๊ทธ๋์ ๋์ฐ๋ณ์ด ๊ธฐ๋ฅ์ ํ์ฅํ์ ๋ redux์ ๊ฐ์๊ธฐ ๋ฐ ์ก์ ์์ฑ๊ธฐ ํจํด๊ณผ ๋งค์ฐ ์ ์ฌํด ๋ณด์์ต๋๋ค. ์ด๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๊ทธ๊ฒ์ด ์ค์ ๋ก ์ด๋ฏธ ๊ฑฐ๊ธฐ์ ์์ ๋ ๋ฌด์ธ๊ฐ๋ฅผ ์ฌ๋ฐ๋ช ํ ์์ ์ ๋ณด์ง ๋ชปํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ด๊ฒ์ ์ค๊ณ๋ ๋๋ก ์๋ํฉ๋๋ค. ๊ถ๊ธํ ์ ์ด ์์ผ๋ฉด https://github.com/facebook/react/issues/14110 ์ ์ด์ ๋ํ ๋ ๊ธด ํ ๋ก ์ด ์์ต๋๋ค.
์ด๋ค ์ด์ ๋ก ๊ฐ์
theme
์์ฑ์ด ์๋AppContext
๊ฐ ์๊ณappContextValue.theme
๋ณ๊ฒฝ ์ ์ผ๋ถExpensiveTree
๋ง ๋ค์ ๋ ๋๋งํ๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.TLDR์ ํ์ฌ๋ก์๋ ์ธ ๊ฐ์ง ์ต์ ์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
์ต์ 1(์ ํธ): ํจ๊ป ๋ณ๊ฒฝ๋์ง ์๋ ๋ถํ ์ปจํ ์คํธ
๋ง์ ๊ตฌ์ฑ ์์์์
appContextValue.theme
๊ฐ ํ์ํ์ง๋งappContextValue
์์ฒด๊ฐ ๋๋ฌด ์์ฃผ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐThemeContext
์์AppContext
ThemeContext
๋ฅผ ๋ถํ ํ ์ ์์ต๋๋ค.์ด์
AppContext
๋ณ๊ฒฝํด๋ThemeContext
์๋น์๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ต๋๋ค.์ด๊ฒ์ ์ ํธ๋๋ ์์ ์ฌํญ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ํน๋ณํ ๊ตฌ์ ๊ธ์ต์ด ํ์ํ์ง ์์ต๋๋ค.
์ต์ 2: ๊ตฌ์ฑ ์์๋ฅผ ๋๋ก ๋๋๊ณ ๊ทธ ์ฌ์ด์
memo
๋ฅผ ๋ฃ์ต๋๋ค.์ด๋ค ์ด์ ๋ก ์ปจํ ์คํธ๋ฅผ ๋ถํ ํ ์ ์๋ ๊ฒฝ์ฐ์๋ ๊ตฌ์ฑ ์์๋ฅผ ๋๋ก ๋ถํ ํ๊ณ ๋ด๋ถ ๊ตฌ์ฑ ์์์ ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ props๋ฅผ ์ ๋ฌํ์ฌ ๋ ๋๋ง์ ์ต์ ํํ ์ ์์ต๋๋ค. ๋น์ ์ ์ฌ์ ํ โโ๋ฐ๊นฅ ์ชฝ์ ๋ ๋๋งํ์ง๋ง ์๋ฌด ๊ฒ๋ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ ๋ ดํด์ผํฉ๋๋ค.
์ต์ 3: ๋ด๋ถ์
useMemo
๊ตฌ์ฑ์์ 1๊ฐ๋ง์ง๋ง์ผ๋ก ์ฝ๋๋ฅผ ์ข ๋ ์ฅํฉํ๊ฒ ๋ง๋ค ์ ์์ง๋ง ๋ฐํ ๊ฐ์
useMemo
๋ก ๋ํํ๊ณ ์ข ์์ฑ์ ์ง์ ํ์ฌ ๋จ์ผ ๊ตฌ์ฑ ์์์ ์ ์งํ ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๋ ์ฌ์ ํ ์ฌ์คํ๋์ง๋ง ๋ชจ๋useMemo
์ ๋ ฅ์ด ๋์ผํ ๊ฒฝ์ฐ React๋ ์์ ํธ๋ฆฌ๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ต๋๋ค.์์ผ๋ก ๋ ๋ง์ ์๋ฃจ์ ์ด ์์ ์ ์์ง๋ง ์ด๊ฒ์ด ํ์ฌ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ ๋๋ค.
๊ทธ๋๋ ์ต์ 1์ด ๋ ์ข์ต๋๋ค. ์ผ๋ถ ์ปจํ ์คํธ๊ฐ ๋๋ฌด ์์ฃผ ๋ณ๊ฒฝ๋๋ฉด ๋ถํ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.