๋ง์ฝ, prop์ ๋๊ธฐ๋ ๊ฒ์ ์ค์ด๊ณ ์ถ์ ์ด์ ๋ผ๋ฉด Component Composition (์ปดํฌ๋ํธ ํฉ์ฑ์ ๋ฐฉ๋ฒ๋ ์๋ค) ๋ฐฉ๋ฒ๋ ์๋ค. prop ๋์ ์ ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด๋ค. ์ฌ๋ฌ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋๊ธธ ์ ์๋ค.
function Page(props) {
const user = props.user;
const content = <Feed user={user} />;
const topBar = (
<NavigationBar>
<Link href={user.permalink}>
<Avatar user={user} size={props.avatarSize} />
</Link>
</NavigationBar>
);
return (
<PageLayout
topBar={topBar}
content={content}
/>
);
}
๋จ์ํ ์ ๋ฌ์ด ์๋,
๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ ๋ฒจ์ ์ปดํฌ๋ํธ์ ์๋ ค์ผํ ํ์๊ฐ ์์ ๋ context๋ฅผ ์ฐ๋ ๊ฒ์ด ์ข๋ค. ์๋ฅผ ๋ค๋ฉด ๋ก๊ทธ์ธ ์ ๋ณด, ํ
๋ง, ๋ฐ์ดํฐ ์บ์ ๋ฑ์ ๊ด๋ฆฌํ ๋ ์ด๋ค.
const MyContext = React.createContext(defaultValue)
์ ์ญ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
defaultValue
๋ ์ ์ ํ Provider ์ง์ ์ฐพ์ง ๋ชปํ ๋ ์ฌ์ฉ๋๋ value
<MyContext.Provider value={//์ ๋ฌํ๋ ๋ฐ์ดํฐ}>
Provider๋ context๋ฅผ ๊ตฌ๋
ํ๋ ์ปดํฌ๋ํธ(consumer)์ context์ ๋ณํ๋ฅผ ์๋ฆฌ๋ ์ญํ ์ ํ๋ค. value๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค Providerํ์์์ context๋ฅผ ๊ตฌ๋
ํ๋ ์ปดํฌ๋ํธ๋ค์ ๋ค์ ๋ ๋๋ง ์ํจ๋ค.
<MyContext.Consumer>
{value=><div>name: {value}</div>}
</MyContext.Consumer>
context์ ๋ณํ๋ฅผ ๊ตฌ๋ ํ๋ ์ปดํฌ๋ํธ์ด๋ฉฐ context์ ๊ฐ์ ๋ฐ์ React Node๋ฅผ ๋ฐํํ๋ค. value ๋งค๊ฐ๋ณ์๋ Provider ์ค ์์ํธ๋ฆฌ์์ ๊ฐ์ฅ ๊ฐ๊น์ด Provider์ prop๊ณผ ๋์ผํ๋ค. ๋ง์ผ, ์์์ Provider๊ฐ ์กด์ฌํ์ง ์๋ค๋ฉด context๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ์ง์ ํ defaultValue์ ๋์ผํ ๊ฒ์ด๋ค.
Provider์ Consumer๋ฅผ ์ค์ฒฉํ์ฌ ์์ฑํด ์ฌ๋ฌ context๋ฅผ ๊ตฌ๋ ํ ์ ์๋ค.
// ๊ธฐ๋ณธ๊ฐ์ด light์ธ ThemeContext
const ThemeContext = React.createContext('light');
// ๋ก๊ทธ์ธํ ์ ์ ์ ๋ณด๋ฅผ ๋ด๋ UserContext
const UserContext = React.createContext({
name: 'Guest',
});
class App extends React.Component {
render() {
const {signedInUser, theme} = this.props;
// context ์ด๊ธฐ๊ฐ์ ์ ๊ณตํ๋ App ์ปดํฌ๋ํธ
return (
<ThemeContext.Provider value={theme}>
<UserContext.Provider value={signedInUser}>
<Layout />
</UserContext.Provider>
</ThemeContext.Provider>
);
}
}
function Layout() {
return (
<div>
<Sidebar />
<Content />
</div>
);
}
// ์ฌ๋ฌ context์ ๊ฐ์ ๋ฐ๋ ์ปดํฌ๋ํธ
function Content() {
return (
<ThemeContext.Consumer>
{theme => (
<UserContext.Consumer>
{user => (
<ProfilePage user={user} theme={theme} />
)}
</UserContext.Consumer>
)}
</ThemeContext.Consumer>
);
}
Consumer๋ก ๊ฐ์ธ๋ฒ๋ฆฐ ๊ณต๊ฐ ๋ด์์๋ value๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์๋๋ฐ, ๋จ์ ์ผ๋ก๋ ์ ์ญ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ปดํฌ๋ํธ์์๋ ๋ ๋๋ง์ด ๋ฐ์ํ๋ค.
๋๋ฌธ์ Consumer๋ก๋ ์ ๋ง ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋ ์ปดํฌ๋ํธ๋ง ๊ฐ์ธ๋๋ก ํด์ผํ๋ค.
๋ํ, Provider์์ ์ ์ญ์ํ๋ก ๋๊ธธ prop์ ์ง์ ์ ์ธํด ์ ๊ฐ์ฒด๋ก ์ธ์ํ์ง ์๋๋ก ํด์ผํ๋ค. ์๋ก์ด ๊ฐ์ฒด๋ก ์ธ์ํ๋ฉด Provider๊ฐ ๋ ๋๋ง ๋ ๋ ํ์์ ๊ตฌ๋ ํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ด ๋ ๋๋ง๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
class App extends React.Component {
render() {
return (
<MyContext.Provider value={{something: 'something'}}>
<Toolbar />
</MyContext.Provider>
);
}
}
{{something: 'something'}}
์๋ก์ด ๊ฐ์ฒด๋ก ๋ณด๊ณ Toolbar๋ฅผ ํญ์ ๋ ๋๋ง ์ํค๊ฒ ๋๋ค. ์ด๋ฅผ ๋ง๊ธฐ ์ํด ๊ฐ์ฒด์ ๊ฐ์ ๋ถ๋ชจ์ state๋ก ๋์ด์ฌ๋ ค ๊ด๋ฆฌํด์ผํ๋ค.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'}, //state์ ์ ์ธ!
};
}
render() {
return (
<MyContext.Provider value={this.state.value}>
<Toolbar />
</MyContext.Provider>
);
}
}
Consumer๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด๋ค. ์ปดํฌ๋ํธ๋ค์ ๊ฐ์ ํ์์์ด,
์ ์ญ์ํ๋ฅผ ์ฌ์ฉํ ๊ณณ์์ const globalState = useContext(SampleContext)
์ ๊ฐ์ด ์ ์ธํ๋ฉด globalState
๊ฐ ํด๋น ํ
์ด ์ ์ธ๋ ์ปดํฌ๋ํธ์์ ๊ฐ์ฅ ๊ฐ๊น์ด Provider์ ์ํ๊ฐ์ ๊ฐ๊ฒ ๋๋ค.
์ด ๋, context๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด useContext๋ Consumer์ ๋์ผํ๊ฒ ํธ์ถํ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ์ํจ๋ค.
useState
์ฒ๋ผ ์ํ๋ง์ ๋ฐํํ์ง ์๊ณ ์ด์ state์ ์์กดํ์ฌ ์ฌ๋ฌ ์กฐ๊ฑด์ ๋ํด ์๋ก์ด state๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ ์ ์ฉํ๋ค. ์ฝ๋ฐฑ ๋์ ์ dispatch๋ฅผ ์ ๋ฌํ ์ ์๊ธฐ ๋๋ฌธ์ ์ํ์
๋ฐ์ดํธ๋ฅผ ์ํค๋ ์ปดํฌ๋ํธ๋ฅผ ์ต์ ํํ ์ ์๋ค.
(dispatch๋ ๋ค์ ๋ ๋๋ง์ ์ํค์ง ์๋๋ค.)