๊ธฐ๋ฅ ์ ์์ฒญํ๊ฑฐ๋ ๋ฒ๊ทธ๋ฅผ ๋ณด๊ณ ํ์๊ฒ ์ต๋๊น?
๊ธฐ๋ฅ์ด์ง๋ง ์ API๊ฐ ์ด์ unstable_rendersubtreeintocontainer
์ค๋จ์ํค๋ ๋ฒ๊ทธ๋ ์์ต๋๋ค.
ํ์ฌ ํ๋์ ๋ฌด์์
๋๊น?
ํฌํธ์์ React ํธ๋ฆฌ ์กฐ์์ผ๋ก์ ๋ชจ๋ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ฉ์ถ ์๋ ์์ต๋๋ค. ๋ชจ๋ฌ/ํ์ค๋ฒ๊ฐ ์๋ ๋ ์ด์ด ๋ฉ์ปค๋์ฆ์ด ์์ ํ ์์๋์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋๋กญ๋ค์ด ๋ฒํผ์ด ์์ต๋๋ค. ํด๋ฆญํ๋ฉด ํ์ค๋ฒ๊ฐ ์ด๋ฆฝ๋๋ค. ์ฐ๋ฆฌ๋ ๋ํ ๊ฐ์ ๋ฒํผ์ ํด๋ฆญํ ๋ ์ด ํ์ค๋ฒ๋ฅผ ๋ซ๊ณ ์ถ์ต๋๋ค. createPortal์ ์ฌ์ฉํ์ฌ ํ์ค๋ฒ ๋ด๋ถ๋ฅผ ํด๋ฆญํ๋ฉด ๋ฒํผ์ด ํด๋ฆญ๋๊ณ ๋ซํ๋๋ค. ์ด ๊ฐ๋จํ ๊ฒฝ์ฐ์ stopPropagation์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ทธ๋ฌํ ๊ฒฝ์ฐ๊ฐ ๋ง๊ณ ๋ชจ๋ ๊ฒฝ์ฐ์ stopPropagation์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ํ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์ค์งํ ์๋ ์์ต๋๋ค.
์์๋๋ ๋์์ ๋ฌด์์
๋๊น?
createPortal์๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์๋์ผ๋ก ์ค์งํ์ง ์๊ณ React ํธ๋ฆฌ๋ฅผ ํตํ ํฉ์ฑ ์ด๋ฒคํธ ์ ํ๋ฅผ ์ค์งํ๋ ์ต์
์ด ์์ด์ผ ํฉ๋๋ค. ์ด๋ป๊ฒ ์๊ฐํ๋์?
๋ํ mouseOver/Leave์ ์ ํ๋ ์์ ํ ์์์น ๋ชปํ ๊ฒ์ฒ๋ผ ๋ณด์
๋๋ค.
ํฌํธ์ ๋ฒํผ ๋ฐ์ผ๋ก ์ด๋ํ ์ ์์ต๋๊น?
์
return [
<div key="main">
<p>Hello! This is first step.</p>
<Button key="button" />
</div>,
<Portal key="portal" />
];
๊ทธ๋ฌ๋ฉด ๋ฒํผ์ ํตํด ๊ฑฐํ์ด ๋ฐ์ํ์ง ์์ต๋๋ค.
๋ด ์ฒซ ๋ฒ์งธ ์๊ฐ์ด์์ง๋ง!) ์ด๋ฌํ ๊ตฌ์ฑ ์์ ์ปจํ ์ด๋์ mouseEnter ์ฒ๋ฆฌ๊ธฐ๊ฐ ์๋ค๊ณ ์์ํด๋ณด์ญ์์ค.
ํจ๊ป unstable_rendersubtreeintocontainer
๋ด๊ฐ ํ์ ์๋ฌด๊ฒ๋์ ์ด๋ฒคํธ์๋ ButtonWithPopover
๊ตฌ์ฑ ์์ - ๋ง์ฐ์ค๊ฐ ์ ๋ง ๋ค์ด๊ฐ ๋ mouseEnter ๋จ์ํ ์๋ div
๋ฒํผ์ DOM ์์๋ฅผ, ๋ง์ฐ์ค๊ฐ ํ ์ค๋ฒ ์์์์ ๋ ํด๊ณ ์์ต๋๋ค. ํฌํธ์ ์ฌ์ฉํ๋ฉด ํ์ค๋ฒ ์๋ก ๋ง์ฐ์ค๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด ์๊ฐ์๋ ์ค์ ๋ก div
๊ฐ ์๋๋๋ค. ๋ฐ๋ผ์ ์ ํ๋ฅผ ์ค๋จํด์ผ ํฉ๋๋ค. ButtonWithPopover
๊ตฌ์ฑ ์์์์ ์ํํ๋ฉด ๋ง์ฐ์ค๊ฐ ๋ฒํผ ์์ ์์ ๋ ์ด๋ฒคํธ ๋ฐ์์ด ์ค๋จ๋ฉ๋๋ค. ํ์ค๋ฒ์์ ์ด ์์
์ ์ํํ๊ณ ์ด ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ํด ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ํ์ค๋ฒ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ์ฑ ๋ถ๋ถ์์ ๋
ผ๋ฆฌ๋ฅผ ์ค๋จํ ์๋ ์์ต๋๋ค.
๋๋ React ํธ๋ฆฌ๋ฅผ ํตํด ๋ฒ๋ธ ๋งํ๋ ๋ชฉ์ ์ ์ ๋ง๋ก ์ดํดํ์ง ๋ชปํฉ๋๋ค. ํฌํธ ๊ตฌ์ฑ ์์์์ ์ด๋ฒคํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ โ ๋จ์ํ props๋ฅผ ํตํด ํธ๋ค๋ฌ๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ unstable_rendersubtreeintocontainer
๋ก ๊ทธ๊ฒ์ ํ๊ณ ์๋ฒฝํ๊ฒ ์๋ํ์ต๋๋ค.
๋ฐ์ ํธ๋ฆฌ์ ๊น์ํ ์ผ๋ถ ๋ฒํผ์์ ๋ชจ๋ฌ ์ฐฝ์ ์ด๋ฉด ๋ชจ๋ฌ์์ ์๊ธฐ์น ์์ ์ด๋ฒคํธ ๋ฐ์์ด ๋ฐ์ํฉ๋๋ค. stopPropagation
๋ DOM์์ ์ ํ๋ฅผ ์ค์งํ๊ณ ์ค์ ๋ก ํด๊ณ ๋ ๊ฒ์ผ๋ก ์์๋๋ ์ด๋ฒคํธ๋ฅผ ์ป์ง ๋ชปํ ๊ฒ์
๋๋ค(
@gaearon ๋๋ ์ด๊ฒ์ด ๊ธฐ๋ฅ ์์ฒญ๋ณด๋ค ๋ ๋ง์ ๋ฒ๊ทธ๋ผ๊ณ ์ ์ํ๊ณ ์ถ์ต๋๋ค. ํฌํธ(์ด์ ์ unstable_rendersubtreeintocontainer
์ฌ์ฉํ๋ ๊ณณ)์ ํตํด ๋ฐ์ํ๋ ๋ง์ฐ์ค ์ด๋ฒคํธ๋ก ์ธํด ๋ฐ์ํ๋ ์๋ก์ด ๋ฒ๊ทธ๊ฐ ๋ง์ด ์์ต๋๋ค. ์ด๋ค ์ค ์ผ๋ถ๋ ๋ง์ฐ์ค ์ด๋ฒคํธ๋ฅผ ํํฐ๋งํ๊ธฐ ์ํ ์ถ๊ฐ div ๋ ์ด์ด๋ก๋ ์์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋๋๊ทธ ๊ฐ๋ฅํ ๋ํ ์์๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๋ฌธ์๋ก ์ ํ๋๋ mousemove ์ด๋ฒคํธ์ ์์กดํ๊ธฐ ๋๋ฌธ์
๋๋ค.
ํฅํ ๋ฆด๋ฆฌ์ค์์ ์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๊ธฐ ์ ์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
ํฌํธ์ ํ์ฌ ๊ฑฐํ ๋์์ด ์์๋๊ณ ์๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ฅ ์์ฒญ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ชฉํ๋ ํ์ ํธ๋ฆฌ๊ฐ ๋ถ๋ชจ์ ์ค์ ์์์ฒ๋ผ ์๋ํ๋ ๊ฒ์ ๋๋ค.
๋์์ด ๋๋ ๊ฒ์ ํ์ฌ ๊ตฌํ์์ ์ ๊ณต๋์ง ์๊ฑฐ๋ ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ด ์ถ๊ฐ ์ฌ์ฉ ์ฌ๋ก ๋๋ ์ํฉ(์ง๊ธ ๋ณด๊ณ ์๋ ๊ฒ๊ณผ ๊ฐ์)์ ๋๋ค.
์ด ๋์์ด ์๋๋ ๊ฒ์์ ์ดํดํ์ง๋ง ๋นํ์ฑํํ ์ ์๋ ์ค์ํ ๋ฒ๊ทธ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ด ๋ง์์ DOM์ผ๋ก ์์ ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ DOM ๊ตฌํ ๋์์ ์์์ํค์ง ์๊ณ ๋ณด์กดํด์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด:
class Container extends React.Component {
shouldComponentUpdate = () => false;
render = () => (
<div
ref={this.props.containerRef}
// Event propagation on this element not working
onMouseEnter={() => { console.log('handle mouse enter'); }}
onClick={() => { console.log('handle click'); }}
/>
)
}
class Root extends React.PureComponent {
state = { container: null };
handleContainer = (container) => { this.setState({ container }); }
render = () => (
<div>
<div
// Event propagation on this element not working also
onMouseEnter={() => { console.log('handle mouse enter'); }}
onClick={() => { console.log('handle click'); }}
>
<Container containerRef={this.handleContainer} />
</div>
{this.state.container && ReactDOM.createPortal(
<div>Portal</div>,
this.state.container
)}
</div>
);
}
DOM์ผ๋ก ์์ ํ ๋ DOM ๊ตฌํ๊ณผ ๊ฐ์ ์ด๋ฒคํธ๋ฅผ ์์ ํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ๋ด ์์ ์์ ์ด๋ฒคํธ๋ Portal ์ ํตํด ์ ํ๋๊ณ DOM ๋ถ๋ชจ๋ฅผ ์ฐํํ๋ฉฐ ์ด๋ ๋ฒ๊ทธ ๋ก ๊ฐ์ฃผ๋ ์ ์์ต๋๋ค.
ํ ๋ก ์ ํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๋ฒ๊ทธ์ธ์ง ์๋์ง๋ฅผ ๋ ผํ๋ ๊ฒ์ ๊ทธ๋ค์ง ๋์์ด ๋์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋์ ํ์ฌ ๋์์ผ๋ก ์ถฉ์กฑ๋์ง ์๋ ์ฌ์ฉ ์ฌ๋ก์ ์๋ฅผ ๋ ผ์ํ๋ ๊ฒ์ด ๋ ์์ฐ์ ์ด๋ฏ๋ก ํ์ฌ ๋ฐฉ์์ด ๋ฏธ๋๋ฅผ ์ํ ์ต์ ์ ๋ฐฉ๋ฒ์ธ์ง ๋ ์ ์ดํดํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๋ API๊ฐ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ณผ๋ํ๊ฒ ์ ํํ์ง ์์ผ๋ฉด์ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ํต์ฌ ํ์ ๋ํด ๋งํ ์๋ ์์ง๋ง ๊ตฌ์ฑ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒ์ ๊ฐ๋ฅํ ์๋ฃจ์ ์ด ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก React๋ ๊ตฌ์ฑ ๊ฐ๋ฅํ API๋ณด๋ค ์ผ๊ด๋ API๋ฅผ ์ ํธํฉ๋๋ค.
๋๋ ๋ํ ์ด ๋์์ด DOM์ด ์๋ํ๋ ๋ฐฉ์์ด ์๋๋ผ๋ ๊ฒ์ ์ดํดํ์ง๋ง, ๊ทธ ์์ฒด๋ก ๊ทธ๋ ๊ฒ ๋์ด์๋ ์ ๋๋ค๊ณ ๋งํ ์ข์ ์ด์ ๋ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. react-dom์ ๋ง์ ๋์์ DOM์ด ์๋ํ๋ ๋ฐฉ์๊ณผ ๋ค๋ฅด๋ฉฐ ์ด๋ฒคํธ๊ฐ ์ด๋ฏธ ๊ธฐ๋ณธ ๋ฒ์ ๊ณผ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด onChange
๋ ๊ธฐ๋ณธ ๋ณ๊ฒฝ ์ด๋ฒคํธ์ ์์ ํ ๋ค๋ฅด๋ฉฐ DOM๊ณผ ๋ฌ๋ฆฌ ๋ชจ๋ ๋ฐ์ ์ด๋ฒคํธ๋ ์ ํ์ ๊ด๊ณ์์ด ๋ฒ๋ธ๋ง๋ฉ๋๋ค.
๋์ ํ์ฌ ๋์์ผ๋ก ์ถฉ์กฑ๋์ง ์๋ ์ฌ์ฉ ์ฌ๋ก์ ์๋ฅผ ๋ ผ์ํ๋ ๊ฒ์ด ๋ ์์ฐ์ ์ ๋๋ค.
๋ค์์ React 16์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ ๋ ๊นจ์ง ๋ ๊ฐ์ง ์์ ๋๋ค.
๋จผ์ ๋ฒํผ์ผ๋ก ์คํ๋๋ ๋๋๊ทธ ๊ฐ๋ฅํ ๋ํ ์์๊ฐ ์์ต๋๋ค. ๋ชจ๋ ๋ง์ฐ์ค* ํค* ์ด๋ฒคํธ์ ๋ํด StopPropagation์ ํธ์ถํ๋ ํฌํธ ์ฌ์ฉ์ "ํํฐ๋ง" ์์๋ฅผ ์ถ๊ฐํ๋ ค๊ณ ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋๊ทธ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด ๋ฌธ์์ mousemove ์ด๋ฒคํธ๋ฅผ ๋ฐ์ธ๋ฉํ ์ ์์ด์ผ ํฉ๋๋ค. ์ด๋ ์ฌ์ฉ์๊ฐ ๋ง์ฐ์ค๋ฅผ ์๋นํ ์๋๋ก ์์ง์ด๋ฉด ์ปค์๊ฐ ๋ํ ์์์ ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ ๋๋ค. ๋ ๋์ ์์ค์์ ๋ง์ฐ์ค ์์ง์์ ์บก์ฒํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ด๋ฒคํธ๋ฅผ ํํฐ๋งํ๋ฉด ์ด ๊ธฐ๋ฅ์ด ์ค๋จ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ Portal์ ์ฌ์ฉํ๋ฉด ๋ง์ฐ์ค ๋ฐ ํค ์ด๋ฒคํธ๊ฐ ๋ํ ์์ ๋ด๋ถ์์ ์ด๋ฅผ ์คํํ ๋ฒํผ์ผ๋ก ๋ฒ๋ธ๋ง๋์ด ๋ค๋ฅธ ์๊ฐ ํจ๊ณผ๋ฅผ ํ์ํ๊ณ ๋ํ ์์๋ฅผ ๋ซ๊ฒ ๋ง๋ค ์๋ ์์ต๋๋ค. ํฌํธ์ ํตํด ์์๋ ๋ชจ๋ ๊ตฌ์ฑ ์์๊ฐ ์ด ์ด๋ฒคํธ ์ ํ๋ฅผ ์ค์งํ๊ธฐ ์ํด 10-20๊ฐ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ด ํ์ค์ ์ด์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋์งธ, ๊ธฐ๋ณธ ๋๋ ๋ณด์กฐ ๋ง์ฐ์ค ํด๋ฆญ์ผ๋ก ์คํํ ์ ์๋ ํ์ ์ปจํ ์คํธ ๋ฉ๋ด๊ฐ ์์ต๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ด๋ถ ์๋น์ ์ค ํ๋๋ ์ด ๋ฉ๋ด๋ฅผ ์์ํ๋ ์์์ ์ฐ๊ฒฐ๋ ๋ง์ฐ์ค ํธ๋ค๋ฌ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ๋ฌผ๋ก ๋ฉ๋ด์๋ ํญ๋ชฉ ์ ํ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํด๋ฆญ ํธ๋ค๋ฌ๋ ์์ต๋๋ค. mousedown/mousedown ์ด๋ฒคํธ๊ฐ ๋ฉ๋ด๋ฅผ ์์ํ๋ ๋ฒํผ์ผ๋ก ๋ค์ ๋ฒ๋ธ๋ง๋๋ฏ๋ก ํด๋ฆญํ ๋๋ง๋ค ๋ฉ๋ด๊ฐ ๋ค์ ๋ํ๋ฉ๋๋ค.
ํต์ฌ ํ์ ๋ํด ๋งํ ์๋ ์์ง๋ง ๊ตฌ์ฑ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒ์ ๊ฐ๋ฅํ ์๋ฃจ์ ์ด ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก React๋ ๊ตฌ์ฑ ๊ฐ๋ฅํ API๋ณด๋ค ์ผ๊ด๋ API๋ฅผ ์ ํธํฉ๋๋ค.
๋๋ ๋น์ (๊ณผ ํ)์ด ์ด ํน๋ณํ ๊ฒฝ์ฐ์ ์ด ์
์ฅ์ ์ฌ๊ณ ํ ๊ฒ์ ๊ฐ์ฒญํฉ๋๋ค. ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ํฅ๋ฏธ๋ก์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค(๋น๋ก ์ง์ ์ ์ผ๋ก ์๊ฐํ ์๋ ์์ง๋ง). ๊ทธ๋ฌ๋ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ์ฅ์ ๊ฐ ๋ ๊ฒ์ด๋ฉฐ API์ ์๋นํ ๋ถ์ผ์น๊ฐ ๋ฐ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. unstable_rendersubtreeintocontainer
๋ ์ ๋ ์ง์๋์ง ์์์ง๋ง ๋ชจ๋ ์ฌ๋์ด ์ง์ ํธ๋ฆฌ ์ธ๋ถ์์ ๋ ๋๋งํ๋ ๋ฐ ์ฌ์ฉํ์ผ๋ฉฐ ์ด ๋ฐฉ์์ผ๋ก ์๋ํ์ง ์์์ต๋๋ค. ๊ณต์์ ์ผ๋ก๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ผ๋ฉฐ Portal์ ์ ํธํ์ง๋ง Portal์ ์ด ์ค์ํ ๋ฐฉ์์ผ๋ก ๊ธฐ๋ฅ์ ์ค๋จํ๋ฉฐ ์ฌ์ด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์๋นํ ์ผ๊ด์ฑ์ด ์๋ค๊ณ ์ค๋ช
ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋ํ ์ด ๋์์ด DOM์ด ์๋ํ๋ ๋ฐฉ์์ด ์๋๋ผ๋ ๊ฒ์ ์ดํดํ์ง๋ง, ๊ทธ ์์ฒด๋ก ๊ทธ๋ ๊ฒ ๋์ด์๋ ์ ๋๋ค๊ณ ๋งํ ์ข์ ์ด์ ๋ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋น์ ์ด ์ฌ๊ธฐ์์ ์ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ด ๊ฒฝ์ฐ (a) ์ด๊ฒ์ (b) ํ์ฌ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๋ ๊ทผ๋ณธ์ ์ธ ๋์์ด๋ฏ๋ก "DOM์ด ์ด๋ฐ ์์ผ๋ก ์๋ํ์ง ์์ต๋๋ค"๋ผ๋ ๊ฐ๋ ฅํ ์ฃผ์ฅ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์์ ํ ์ค๋๋ ฅ์ด ์๋ค๋ฉด.
๊ทธ๋ฆฌ๊ณ ๋ถ๋ช ํ ๋ง์๋๋ฆฌ์๋ฉด, ์ด๊ฒ์ ๋ฒ๊ทธ๋ก ๊ฐ์ฃผํด ๋ฌ๋ผ๋ ์ ์์ฒญ์ ๋๋ถ๋ถ ๋์ค์๋ณด๋ค ๋นจ๋ฆฌ ์์ ์ ์ํด ์ฐ์ ์์๋ฅผ ์ง์ ํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
Portal์ ๋ํ ์ ๋ฉํ ๋ชจ๋ธ์ ๋ง์น ํธ๋ฆฌ์ ๊ฐ์ ์์น์ ์๋ ๊ฒ์ฒ๋ผ ์๋ํ์ง๋ง "์ค๋ฒํ๋ก: ์จ๊น"๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํผํ๊ณ ๊ทธ๋ฆฌ๊ธฐ/๋ ์ด์์ ๋ชฉ์ ์ผ๋ก ์คํฌ๋กคํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค.
ํฌํธ ์์ด ์ธ๋ผ์ธ์ผ๋ก ๋ฐ์ํ๋ ์ ์ฌํ "ํ์ " ์๋ฃจ์ ์ด ๋ง์ด ์์ต๋๋ค. ์: ๋ฐ๋ก ์์ ์๋ ์์๋ฅผ ํ์ฅํ๋ ๋ฒํผ.
์ฌ๊ธฐ GitHub์์ "๋ฐ์ ์ ํ" ๋ํ ์์๋ฅผ ์๋ก ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ๋ฒํผ ๋ฐ๋ก ์์ div๋ก ๊ตฌํ๋ฉ๋๋ค. ์ง๊ธ์ ์ ์๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ค๋ฅธ z-์์ธ์ ๊ฐ๊ฑฐ๋ ์ด๋ฌํ ์ฃผ์์ด ํฌํจ๋ overflow: scroll
์์ญ์์ ์ ๊ฑฐํ๋ ค๋ฉด DOM ์์น๋ฅผ ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ์ด๋ฒคํธ ๋ฒ๋ธ๋ง๊ณผ ๊ฐ์ ๋ค๋ฅธ ํญ๋ชฉ๋ ๋ณด์กด๋์ง ์๋ ํ ํด๋น ๋ณ๊ฒฝ์ ์ํํ๋ ๊ฒ์ด ์์ ํ์ง ์์ต๋๋ค.
"ํ์ " ๋๋ "ํ์์"์ ๋ ๊ฐ์ง ์คํ์ผ์ ๋ชจ๋ ํฉ๋ฒ์ ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ๊ตฌ์ฑ ์์๊ฐ ๋ ์ด์์ ์ธ๋ถ์ ๋ ์๋ ๊ฒ๊ณผ ๋์กฐ์ ์ผ๋ก ๋ ์ด์์์ ์ธ๋ผ์ธ์ธ ๊ฒฝ์ฐ ๋์ผํ ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์ต๋๊น?
๋๋ฅผ ์ํด ์ผํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ํฌํธ ๋ ๋๋ง์์ ์ง์ stopPropagation
ํธ์ถํ๋ ๊ฒ์
๋๋ค.
return createPortal(
<div onClick={e => e.stopPropagation()}>{this.props.children}</div>,
this.el
)
ํฌํธ์ ์ฌ์ฉํ๋ ๋จ์ผ ์ถ์ํ ๊ตฌ์ฑ ์์๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ ์๊ฒ ํจ๊ณผ์ ์
๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ชจ๋ createPortal
ํธ์ถ์ ์์ ํด์ผ ํฉ๋๋ค.
@methyl ์ด๊ฒ์ ํธ๋ฆฌ๋ฅผ ๋ฒ๋ธ๋งํ์ง ๋ชปํ๋๋ก ์ฐจ๋จํด์ผ ํ๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์๊ณ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋๊ทธ ๋ํ ์์์ ์ธ๊ธ ๋ ๊ฒฝ์ฐ์, ์ฐ๋ฆฌ๋ ํ์ mousemove
๋ฌธ์์ ๊ฑฐํ๊น์ง๊ฐ ์๋๋ผ ๋ ๋๋ง ๋๋ฌด ์๋ก ๊ฑฐํ์.
"ํ์ " ๋๋ "ํ์์"์ ๋ ๊ฐ์ง ์คํ์ผ์ ๋ชจ๋ ํฉ๋ฒ์ ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ๊ตฌ์ฑ ์์๊ฐ ๋ ์ด์์ ์ธ๋ถ์ ๋ ์๋ ๊ฒ๊ณผ ๋์กฐ์ ์ผ๋ก ๋ ์ด์์์ ์ธ๋ผ์ธ์ธ ๊ฒฝ์ฐ ๋์ผํ ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์ต๋๊น?
@sebmarkbage ์ด ์ง๋ฌธ์ด ์๋ฏธ๊ฐ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ตฌ์ฑ ์์๋ฅผ ์ธ๋ผ์ธํ๋ ๋ฐ ์ด ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ ์ธ๋ผ์ธํ์ง ์์ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ ๋ฌธ์ ์ค ์ผ๋ถ์ ๋ช ๊ฐ์ง ์ฌ์ฉ ์ฌ๋ก๋ผ๊ณ ์๊ฐ renderSubtreeIntoContainer
์ ์ด์๋๊ณ ์๋ค createPortal
๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๊ฐ๋
์ ์ผ๋ก ๋ค๋ฅธ ์ผ์ ํ ๋. Portal์ ๊ฐ๋
์ด ๊ณผ๋ถํ๊ฐ ๊ฑธ๋ฆฐ ๊ฒ ๊ฐ์ต๋๋ค.
๋๋ ๋ชจ๋ฌ ๋ํ ์์์ ๊ฒฝ์ฐ ๋ชจ๋ฌ์ด ๊ทธ๊ฒ์ ์ฐ ๋ฒํผ์ ์์์ฒ๋ผ ์๋ํ๋ ๊ฒ์ ๊ฑฐ์ ์ํ์ง ์๋๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ํธ๋ฆฌ๊ฑฐ ๊ตฌ์ฑ ์์๋ open
์ํ๋ฅผ ์ ์ดํ๊ธฐ ๋๋ฌธ์ ๋ ๋๋ง๋ง ํฉ๋๋ค. ๋ฐ๋ผ์ ๋ฒํผ์ createPortal
๊ฐ ์ด์ ๋ํ ์ฌ๋ฐ๋ฅธ ๋๊ตฌ๊ฐ ์๋๋ผ๊ณ ๋งํ๋ ๋์ ํฌํธ ๊ตฌํ์ด ์๋ชป๋์๋ค๊ณ ๋งํ๋ ๊ฒ์ ์ค์๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ๋ชจ๋ฌ์ ํธ๋ฆฌ๊ฑฐ์ ์์์ด ์๋๋ฏ๋ก ๋ง์น ์๋ ๊ฒ์ฒ๋ผ ๋ ๋๋ง๋์ด์๋ ์ ๋ฉ๋๋ค. ํ ๊ฐ์ง ๊ฐ๋ฅํ ํด๊ฒฐ์ฑ
์ renderSubtreeIntoContainer
๋ฅผ ๊ณ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๋ ๋ค๋ฅธ ์ฌ์ฉ์ ์์ญ ์ต์
์ ๋ ๋๋ง ๋ชจ๋ฌ์ ์ฒ๋ฆฌํ๋ ์ฑ ๋ฃจํธ ๊ทผ์ฒ์ ModalProvider
๋ฅผ ๋๊ณ (์ปจํ
์คํธ๋ฅผ ํตํด) ๋ฃจํธ์ ์์์ ๋ชจ๋ฌ ์์๊ฐ ํ์ํฉ๋๋ค.
renderSubtreeIntoContainer
๋ render
๋ด๋ถ์์ ํธ์ถํ ์ ์๊ฑฐ๋ React 16์ ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋์์ ํธ์ถํ ์ ์์ต๋๋ค. ์ด ์์
์ ์ํํ๋ฉด 16)์ผ๋ก์ ๋ง์ด๊ทธ๋ ์ด์
์์ ์์ ํ ์ค๋จ๋์์ต๋๋ค. ํฌํธ์ ๊ณต์ ๊ถ์ฅ ์ฌํญ์
๋๋ค. https://reactjs.org/blog/2017/09/26/react-v16.0.html#breaking -changes
Portal์ ๊ฐ๋ ์ด ๊ณผ๋ถํ ์ํ๊ฐ ๋์์ ์๋ ์๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ํ์ง๋ง ๊ธ๋ก๋ฒ ๊ตฌ์ฑ ์์์ ์๋ฃจ์ ๊ณผ ์ด์ ๋ํ ์ปจํ ์คํธ๊ฐ ๋ง์์ ๋ค์ง๋ ์์ต๋๋ค. ์ด๋ฒคํธ๊ฐ ๋ฒ๋ธ๋ง๋์ด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ์ง์ ํ๋ createPortal์ ํ๋๊ทธ๋ก ์ด ๋ฌธ์ ๋ฅผ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. 16์ธ ์ด์๊ณผ์ API ํธํ์ฑ์ ์ ์งํ๋ ์ตํธ์ธ ํ๋๊ทธ๊ฐ ๋ ๊ฒ์ ๋๋ค.
ํฌํธ์ ์ฌ์ฉ ์ฌ๋ก์ ์ด๋ฒคํธ ์ ํ๋ฅผ ์ค์งํ๋ ์ต์ ์ ๋ณด๊ณ ์ถ์ดํ๋ ์ด์ ๋ฅผ ๋ช ํํ ํ๋ ค๊ณ ํฉ๋๋ค. ManyChat ์ฑ์์๋ ํฌํธ์ ์ฌ์ฉํ์ฌ '๋ ์ด์ด'๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. ํ์ค๋ฒ, ๋๋กญ๋ค์ด, ๋ฉ๋ด, ๋ชจ๋ฌ๊ณผ ๊ฐ์ ์ฌ๋ฌ ์ ํ์ ๊ตฌ์ฑ ์์์์ ์ฌ์ฉํ๋ ์ ์ฒด ์ฑ์ ๋ํ ๋ ์ด์ด ์์คํ ์ด ์์ต๋๋ค. ๋ชจ๋ ๋ ์ด์ด๋ ์ ๋ ์ด์ด๋ฅผ ๋ ธ์ถํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ฉ๋ด์ ๋ ๋ฒ์งธ ์์ค์ ์๋ ๋ฒํผ์ ๋ค๋ฅธ ๋ฒํผ์ด ํ์ค๋ฒ๋ฅผ ์ด ์ ์๋ ๋ชจ๋ฌ ์ฐฝ์ ํธ๋ฆฌ๊ฑฐํ ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ ์ด์ด๋ ์์ฒด ์์ ์ ํด๊ฒฐํ๋ UX์ ์๋ก์ด ๋ถ๊ธฐ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ ์ด์ด๊ฐ ์ด๋ฆฌ๋ฉด ์ฌ์ฉ์๋ ๋งจ ์๋์ ์๋ ๋ค๋ฅธ ๋ ์ด์ด๊ฐ ์๋๋ผ ์ด ์ ๋ ์ด์ด์ ์ํธ ์์ฉํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ด ์์คํ ์ ๊ฒฝ์ฐ ๋ ์ด์ด์ ๋ ๋๋งํ๊ธฐ ์ํ ๊ณตํต ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ค์์ต๋๋ค.
class RenderToLayer extends Component {
...
stop = e => e.stopPropagation()
render() {
const { open, layerClassName, useLayerForClickAway, render: renderLayer } = this.props
if (!open) { return null }
return createPortal(
<div
ref={this.handleLayer}
style={useLayerForClickAway ? clickAwayStyle : null}
className={layerClassName}
onClick={this.stop}
onContextMenu={this.stop}
onDoubleClick={this.stop}
onDrag={this.stop}
onDragEnd={this.stop}
onDragEnter={this.stop}
onDragExit={this.stop}
onDragLeave={this.stop}
onDragOver={this.stop}
onDragStart={this.stop}
onDrop={this.stop}
onMouseDown={this.stop}
onMouseEnter={this.stop}
onMouseLeave={this.stop}
onMouseMove={this.stop}
onMouseOver={this.stop}
onMouseOut={this.stop}
onMouseUp={this.stop}
onKeyDown={this.stop}
onKeyPress={this.stop}
onKeyUp={this.stop}
onFocus={this.stop}
onBlur={this.stop}
onChange={this.stop}
onInput={this.stop}
onInvalid={this.stop}
onSubmit={this.stop}
>
{renderLayer()}
</div>, document.body)
}
...
}
์ด ๊ตฌ์ฑ ์์๋ React ๋ฌธ์์ ๋ชจ๋ ์ด๋ฒคํธ ์ ํ์ ๋ํ ์ ํ๋ฅผ ์ค์งํ๊ณ React 16์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์์ต๋๋ค.
ํฌํธ์ ์ฐ๊ฒฐํด์ผ ํฉ๋๊น? ํฌํธ์ ์๋๋ฐ์ฑํ๋ ๋์ <React.Sandbox>...</React.Sandbox>
์๋ค๋ฉด ์ด๋จ๊น์?
๊ทธ๋ง์ ๋ ๋์๊ฒ๋ ๋ถํ์ํ๊ฒ ๋ณต์กํด ๋ณด์ธ๋ค. ๋ฒ๋ธ๋ง ๋์์ ์ฐจ๋จํ ์ ์๋๋ก createPortal์ ์ ํ์ ๋ถ์ธ ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
@gaearon ์ด๊ฒ์ ์ฐ๋ฆฌ ์ค ์ผ๋ถ์๊ฒ ๋งค์ฐ ๋ถํํ ์ํฉ์ ๋๋ค. ๊ทํ ๋๋ ๊ทํ์ ์์คํ ์ฌ๋์ด ์ด๊ฒ์ ๋ณผ ์ ์์ต๋๊น? :)
์ ํ์ฌ ์๊ฐ์ ๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ๋ชจ๋ ์ง์๋์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ํ์ฌ ๋ถ๋ชจ์์ ํ์ ํธ๋ฆฌ๋ก ํ๋ฆ์ ์ปจํ ์คํธ๊ฐ ํ์ํ์ง๋ง ํด๋น ํ์ ํธ๋ฆฌ๊ฐ DOM ์ธก๋ฉด์์ ๋ ผ๋ฆฌ์ ์์์ผ๋ก ์๋ํ์ง ์๋๋ก ํ๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์ค์ ๋ก ์์ต๋๋ค. ๋ณต์กํ ๋ชจ๋ฌ์ด ๊ฐ์ฅ ์ข์ ์์ ๋๋ค. ๋ชจ๋ฌ ์ฐฝ์ ์๋ ์์์ ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ ๋ฒํผ๊น์ง ์ ํ๋๋ ๊ฒ์ ๊ฑฐ์ ์ํ์ง ์์ง๋ง ๊ฑฐ์ ํ์คํ ์ ๋ฌ๋ ์ปจํ ์คํธ(i18n, ํ ๋ง ๋ฑ)๊ฐ ํ์ํฉ๋๋ค.
์ด๋ฒคํธ ์ ํ๊ฐ ์๋ฌด ๊ฒ๋ ์ํฅ์ ๋ฏธ์น์ง ์์ ๋งํผ ์ถฉ๋ถํ ๋์ createPortal
๋ฅผ ํตํด ๋ ๋๋งํ๋ ์ฑ ๋ฃจํธ์ ๋ ๊ฐ๊น์ด ModalProvider๋ก ์ ์ค์ผ์ด์ค๋ฅผ _ํ ์ ์๋_ ๋๋ถ๋ถ ํด๊ฒฐ๋ ์ ์์ง๋ง ์ด๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ฒ๋ผ ๋๊ปด์ง๊ธฐ ์์ํฉ๋๋ค. ์ ์ค๊ณ๋ ๊ฑด์ถ๋ฌผ. ๋ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ๋ชจ๋ฌ์ด ๋ ์ด์ ์์ฒด ํฌํจ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์๋ฅผ ๋ ์ฑ๊ฐ์๊ฒ ๋ง๋ญ๋๋ค.
๋๋ createPortal
๊ฐ ๋ ๊ฐ์ง ๋ชจ๋๋ฅผ ์ํํด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์๋ API ์ธก๋ฉด์์ ์ถ๊ฐํ ๊ฒ์
๋๋ค. ๋ชจ๋ฌ ์ผ์ด์ค๋ ๊ณ ์ ํ ๋๋ฌด์ ๊ฝค ๊ฐ๊น๊ธฐ ๋๋ฌธ์ ReactDOM.render
(old skool)์ ์ฌ์ฉํ๊ธฐ๋ฅผ ์ ๋ง๋ก ์ํฉ๋๋ค _except_ ์ปจํ
์คํธ ์ ํ๊ฐ ์ข
์ข
ํ์ํฉ๋๋ค.
@kib357์ด ๊ฒ์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ๊ฒฐ๊ณผ ์ธ๋ถ ์ ํ๋ฆฌ์ผ์ด์ ์ ํฌ์ปค์ค ๊ด๋ฆฌ ์ฝ๋์์ ์ง๋จํ๊ธฐ ๋งค์ฐ ์ด๋ ค์ด ๋ฒ๊ทธ๋ฅผ ์์
ํนํ : ํฉ์ฑ ์ด์ ์ด๋ฒคํธ ์ธ stopPropagation๋ฅผ ํธ์ถํ๋ ๊ฒ๋ ์๋ฏธ #document์ ํธ๋ค๋ฌ๋ฅผ ์บก์ฒ์๋ฅผ, ๋ฐ์์ฉ์ ๊ธฐ๋ณธ ํฌ์ปค์ค ์ด๋ฒคํธ์์ ํธ์ถ์ ํฌํธ ์์ธ ์ธ stopPropagation ๋ฐ์ผ๋ก ๋ฒ๋ธ ๋ง์์ ๊ทธ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด์ด ๋ค๋ฅธ ์บก์ฒ ํธ๋ค๋ฌ๋ฅผํ์ง ์์๋ค <body>
. ์ฐ๋ฆฌ๋ ํธ๋ค๋ฌ๋ฅผ #document๋ก ์ด๋ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง React์ ๋ฐ๊ฐ๋ฝ์ ๋ฐ์ง ์๊ธฐ ์ํด ๊ณผ๊ฑฐ์๋ ํนํ ๊ทธ๋ ๊ฒ ํ์ง ์์์ต๋๋ค.
Portal์ ์๋ก์ด ๋ฒ๋ธ๋ง ๋์์ ์ ๋ง ์์์ ๊ฒฝ์ฐ์ฒ๋ผ ๋๊ปด์ง๋๋ค. ๊ทธ ์๊ฒฌ์ด๋ ์ง์ค์ด ๋ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ์ ๋ํด ๊ด์ฌ์ ๊ฐ์ง ์ ์์ต๋๊น? @gaearon? ์ํ 4๊ฐ์์ธ๋ฐ ์ ๋ง ๊ณ ํต์ค๋ฝ์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์์ ํ ์์ ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๋ React 16์ ์ฃผ์ API ๋ณ๊ฒฝ์ด๋ผ๋ ์ ์ ๊ฐ์ํ ๋ ์ด๊ฒ์ด ๋ฒ๊ทธ๋ก ๊ณต์ ํ๊ฒ ์ค๋ช ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@craigkovatch ๋ด ์ธ๋ผ์ธ ์์ ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ง ์ฌ์ ํ ๊ถ๊ธํฉ๋๋ค. ํ์ ์ด ์์์ ํฌ๊ธฐ๋ฅผ ๋ฎ์ถ๊ณ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ํฌ๊ธฐ๊ฐ ์ฃผ์ด์ง ๋ ์ด์์์์ ๋ฌด์ธ๊ฐ๋ฅผ ์๋๋ก ๋ฐ์ด๋ด๊ธฐ ๋๋ฌธ์ ๋ฌด์ธ๊ฐ๋ฅผ ์ธ๋ผ์ธํ๋ ๊ฒ์ ์ค์ํฉ๋๋ค. ๊ทธ๋ฅ ๋์ด๊ฐ ์ ์์ต๋๋ค.
์ ์ฌ์ ์ผ๋ก ํ์ค๋ฒ๋ฅผ ์ธก์ ํ๊ณ ๋์ผํ ํฌ๊ธฐ์ ๋น ์๋ฆฌ ํ์์๋ฅผ ์ฝ์ ํ๊ณ ์๋จ์ ์ ๋ ฌํ๋ ค๊ณ ์๋ํ ์ ์์ง๋ง ์ฌ๋๋ค์ด ํ๋ ์ผ์ ์๋๋๋ค.
๋ฐ๋ผ์ ํ์ค๋ฒ๊ฐ ๋ฒํผ ๋ฐ๋ก ์๊ณผ ๊ฐ์ด ์ฝํ ์ธ ๋ฅผ ์ ์๋ฆฌ์ ํ์ฅํด์ผ ํ๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ํด๊ฒฐํ์๊ฒ ์ต๋๊น? ๋๋ ๊ฑฐ๊ธฐ์์ ์๋ํ๋ ํจํด์ด ๋ ๊ฒฝ์ฐ ๋ชจ๋์์ ์๋ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ฉฐ ํ๋์ ํจํด๋ง ๊ถ์ฅํด์ผ ํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ด๊ฒ์ด ๋ ์๋๋ฆฌ์ค ๋ชจ๋์์ ์๋ํ๋ ํจํด์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
class Foo extends React.Component {
state = {
highlight: false,
showFlyout: false,
};
mouseEnter() {
this.setState({ highlight: true });
}
mouseLeave() {
this.setState({ highlight: false });
}
showFlyout() {
this.setState({ showFlyout: true });
}
hideFlyout() {
this.setState({ showFlyout: false });
}
render() {
return <>
<div onMouseEnter={this.mouseEnter} onMouseLeave={this.mouseLeave} className={this.state.highlight ? 'highlight' : null}>
Hello
<Button onClick={this.showFlyout} />
</div>
{this.state.showFlyout ? <Flyout onHide={this.hideFlyout} /> : null}
</>;
}
}
ํ๋ผ์ด์์์ด ํฌํธ์ธ ๊ฒฝ์ฐ ์๋ํ๋ฉฐ ํฌํธ ์๋ก ๋ง์ฐ์ค๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉด ์ด๋ฒคํธ ์๋ก ๋ง์ฐ์ค๊ฐ ์ด๋ํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ์ค์ํ ๊ฒ์ ํฌํธ์ด ์๋๊ณ ์ธ๋ผ์ธ ํ๋ผ์ด์์์ด์ด์ผ ํ๋ ๊ฒฝ์ฐ์๋ ์๋ํ๋ค๋ ๊ฒ์ ๋๋ค. stopPropagation์ด ํ์ํ์ง ์์ต๋๋ค.
์ฌ์ฉ ์ฌ๋ก์์ ์๋ํ์ง ์๋ ์ด ํจํด์ ๋ฌด์์ ๋๊น?
@sebmarkbage ์ฐ๋ฆฌ๋ ์์ ํ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก Portal์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. <body>
์ ์ต์ข
์์์ผ๋ก ๋ง์ดํธ๋ ์ปจํ
์ด๋๋ก ๋ ๋๋งํ ๋ค์ ์์น ์ง์ (๋๋ก๋ z-์์ธ ํฌํจ)ํฉ๋๋ค. React ๋ฌธ์๋ ์ด๊ฒ์ด ๋์์ธ ์๋์ ๋ ๊ฐ๊น๋ค๊ณ ์ ์ํฉ๋๋ค. ์ฆ, DOM์์ ์์ ํ ๋ค๋ฅธ ์์น๋ก ๋ ๋๋งํฉ๋๋ค. ์ฐ๋ฆฌ์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์ด ์ค๋ ๋์ ์ํ ๋งํผ ์ถฉ๋ถํ ์ ์ฌํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ง๋ง ํจ๊ป ๋ธ๋ ์ธ์คํ ๋ฐ/๋ฌธ์ ํด๊ฒฐ์ ํ๊ณ ์ถ๋ค๋ฉด ๋ค๋ฅธ ํฌ๋ผ์์ ๋ ์์ธํ ๋
ผ์ํ๊ฒ ์ต๋๋ค.
์๋์ ๋ด ์ฌ์ฉ ์ฌ๋ก๋ ๋ ๋ค ์ ๋๋ค. ๋๋ก๋ ํ๋, ๋๋ก๋ ๋ค๋ฅธ ํ๋. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ด๋ จ์ด ์์ต๋๋ค.
<Flyout />
๋ body์ ์ต์ข
์์์ผ๋ก ๋ ๋๋งํ ์ง ์ฌ๋ถ๋ฅผ ์ ํํ ์ ์์ง๋ง ํฌํธ ์์ฒด๋ฅผ ์์์ด ์๋ ํธ๋ฒ๋ง๋ ๊ตฌ์ฑ ์์์ ํ์ ๋ก ๋์ด์ฌ๋ฆฌ๊ธฐ๋ง ํ๋ฉด ์๋๋ฆฌ์ค๊ฐ ์๋ํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ถํธํ๊ณ ๊น์ด ์ค์ฒฉ๋ ๊ตฌ์ฑ ์์์์ ์ฌ๋ฌผ์ ์๊ฐ ์ด๋ํ๋ ๋ฐฉ๋ฒ์ ์ํ๋ ๊ทธ๋ด๋ฏํ ์๋๋ฆฌ์ค๊ฐ ์๋ค๊ณ ์๊ฐํ์ง๋ง ๊ทธ ์๋๋ฆฌ์ค์์๋ ์ปจํ ์คํธ๊ฐ ์ค๊ฐ ์ง์ ์ ์ปจํ ์คํธ์ธ ๊ฒ์ด ๊ด์ฐฎ์ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๊ทธ๊ฒ๋ค์ ๋ณ๊ฐ์ ๋ ๊ฐ์ง ๋ฌธ์ ๋ก ์๊ฐํ๋ค.
์ด๋ฅผ ์ํด ์ฌ๋กฏ API๊ฐ ํ์ํ ์ ์์ต๋๋ค.
class Foo extends React.Component {
state = {
showFlyout: false,
};
showFlyout() {
this.setState({ showFlyout: true });
}
hideFlyout() {
this.setState({ showFlyout: false });
}
render() {
return <>
Hello
<Button onClick={this.showFlyout} />
<SlotContent name="flyout">
{this.state.showFlyout ? <Flyout onHide={this.hideFlyout} /> : null}
</SlotContent>
</>;
}
}
class Bar extends React.Component {
state = {
highlight: false,
};
mouseEnter() {
this.setState({ highlight: true });
}
mouseLeave() {
this.setState({ highlight: false });
}
render() {
return <>
<div onMouseEnter={this.mouseEnter} onMouseLeave={this.mouseLeave} className={this.state.highlight ? 'highlight' : null}>
<SomeContext>
<DeepComponent />
</SomeContext>
</div>
<Slot name="flyout" />
</>;
}
}
๊ทธ๋ฌ๋ฉด ํฌํธ์ DeepComponent๊ฐ ์๋ Bar์ ์ปจํ ์คํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ์ปจํ ์คํธ ๋ฐ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ฌ์ ํ โโ๋์ผํ ํธ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๊ณต์ ํฉ๋๋ค.
@sebmarkbage ๋ชจ๋ฌ ์ผ์ด์ค๋ ์ผ๋ฐ์ ์ผ๋ก ๋ ๋๋ง๋๋ ์์ ์ ์ปจํ ์คํธ๊ฐ ํ์ํฉ๋๋ค. ๋ด ์๊ฐ์ ๊ทธ๊ฒ์ ์ฝ๊ฐ ๋ ํนํ ๊ฒฝ์ฐ์ ๋๋ค. ๊ตฌ์ฑ ์์๋ ๊ทธ๊ฒ์ ๋ ๋๋งํ ๊ฒ์ ๋ ผ๋ฆฌ์ ์์์ด์ง๋ง ๊ตฌ์กฐ์ ๊ตฌ์ฑ ์์๋ _์๋๋๋ค(๋ ๋์ ๋จ์ด๊ฐ ์๊ธฐ ๋๋ฌธ์). ์๋ฅผ ๋ค์ด ์ผ๋ฐ์ ์ผ๋ก ์์ ์ปจํ ์คํธ(๋ฆด๋ ์ด, formik, redux ์์)์ ๊ฐ์ ๊ฒ์ ์ํฉ๋๋ค. , ๋ฌด์์ด๋ ) ๊ทธ๋ฌ๋ ํต๊ณผํ DOM ์ด๋ฒคํธ๋ ์๋๋๋ค. ๋ํ ๊ทธ๋ฌํ ๋ชจ๋ฌ์ ํธ๋ฆฌ๊ฑฐ ์์ ์๋ ๋๋ฌด ๊น์ํ ๊ณณ์ ๋ ๋๋ง๋์ด ๊ตฌ์กฐ์ ์ผ๋ก ๊ฑฐ๊ธฐ์ ์ํ๊ธฐ ๋๋ฌธ์ ๊ตฌ์ฑ ์์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ ์ํ๋ฅผ ์ ์งํฉ๋๋ค.
์ด ๊ฒฝ์ฐ๋ ์ผ๋ฐ์ ์ผ๋ก createPortal์ด ์ ๊ณตํ๋ ํ๋ผ์ด์์/๋๋กญ๋ค์ด ์ผ์ด์ค์ ๋ค๋ฅด๋ค๊ณ ์๊ฐํฉ๋๋ค. Tbc ํฌํธ์ ๋ฒ๋ธ๋ง ๋์์ ์ข์ง๋ง ๋ชจ๋ฌ์๋ ์ ํฉํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ๋ํ ์ด๊ฒ์ด Context ๋ฐ ์ผ์ข ์ ModalProvider๋ก ํฉ๋ฆฌ์ ์ผ๋ก ์ ์ฒ๋ฆฌ๋ ์ ์๋ค๊ณ ์๊ฐํ์ง๋ง ํนํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ์ฐ ๋ค์ ์ฑ๊ฐ์ ์ผ์ ๋๋ค.
ํฌํธ ์์ฒด๋ฅผ ์์์ด ์๋ ํธ๋ฒ๋ง๋ ๊ตฌ์ฑ ์์์ ํ์ ๋ก ๋์ด์ฌ๋ฆฌ๊ธฐ๋ง ํ๋ฉด ์๋๋ฆฌ์ค๊ฐ ์๋ํฉ๋๋ค.
๋ด๊ฐ ํ๋ก์ฐํ๊ณ ์๋์ง ํ์คํ์ง ์์ต๋๋ค. ์๊ธฐ์น ์์ DOM ํธ๋ฆฌ๋ฅผ ํตํด ๋ฒ๋ธ๋ง๋๋ keyDown ์ด๋ฒคํธ์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์ฌ์ ํ ์์ต๋๋ค.
@jquense ๋ด ์์์ ์ฌ๋กฏ์ ์ฌ์ ํ โโBar ๊ตฌ์ฑ ์์ ๋ด์ ์์ผ๋ฏ๋ก <Form><Bar /></Form>
์ ๊ฐ์ ํ์์ ์ปจํ
์คํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
ํฌํธ์ด ๋ฌธ์ ๋ณธ๋ฌธ์ผ๋ก ๋ ๋๋ง๋๋๋ผ๋.
๋ฐ๋ผ์ ๋ ๊ฐ์ ๊ฐ์ ์ฐธ์กฐ(ํฌํธ๋ง)์ ๊ฐ์ต๋๋ค. deep -> Bar์ ํ์ -> ๋ฌธ์ ๋ณธ๋ฌธ์ ๋๋ค.
๋ฐ๋ผ์ ํฌํธ์ ์ปจํ ์คํธ๋ ์ฌ์ ํ ์์์ ์ปจํ ์คํธ์ด๊ณ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ์ฒด์ธ๋ ๋ง์ฐฌ๊ฐ์ง์ด์ง๋ง ๋ ๋ค ํธ๋ฒ๋ง๋ ๊ฒ์ ์ปจํ ์คํธ์ ์์ต๋๋ค.
๋ค ์ฃ์กํฉ๋๋ค ๋์ณค์ด์ ๐ณ ์ ๊ฐ ์ ๋๋ก ์ฝ๊ณ ์๋ค๋ฉด ๊ทธ๋๋ <Slot>
์์ ๋ฒ๋ธ๋ง์ด ๋จ์์๊ฒ ์ฃ ? Modal ๋ํ ์์์ ๊ฒฝ์ฐ ์๋ง๋ _any_ ๋ฒ๋ธ๋ง์ ์ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ๊ทธ๊ฒ์ ํ์คํ ๋ ์ข์ต๋๋ค. ์คํฌ๋ฆฐ ๋ฆฌ๋์ ๊ด์ ์์ ์๊ฐํ๋ ๊ฒ์ฒ๋ผ ๋ชจ๋ฌ ์ธ๋ถ์ ๋ชจ๋ ํญ๋ชฉ์ด ์ผ์ ธ ์๋ ๋์ ๋ฐ์ ๋๊ธฐ๋ฅผ ์ํฉ๋๋ค. ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ ๊ฒฝ์ฐ ๋ฒ๋ธ๋ง์ด ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์๋ฌด๋ ๋ํ ์์ ๋ด๋ถ์ ํด๋ฆญ์ด ์๋ฌด๋ฐ๋ ๋ฒ๋ธ๋ง๋์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ๋ ํฌํธ์ด ์๋์ง๋ง ํธ๋ฆฌ ๊ฐ์ ์ปจํ
์คํธ๋ฅผ ๊ณต์ ํ ์ ์๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? ์ปจํ
์คํธ์ ์ผ๋ถ์ธ ReactDOM.render
๋ ๋ชจ๋ฌ์ ๋ํด ์ ๋ง ๊ด์ฐฎ๊ณ ์ด์จ๋ ๊ทธ๊ฒ์ ๋ํด ๋ "์ฌ๋ฐ๋ฅธ" ์ฌ๊ณ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค...
์ฌ๊ธฐ์์ ๋ด ์๊ฐ์ ์ฌ์ ํ โโ๋ชจ๋ฌ์์ div, ๋ณธ๋ฌธ, ๋ฌธ์, ์ฐฝ์ผ๋ก ์ด๋ํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ์ ๋ฒ๋ธ๋ง์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ๋ ์ ์ผ๋ก ํ๋ ์์ ๋์ด ํฌํจํ๋ ์ฐฝ ๋ฑ์ผ๋ก ์ด๋ํฉ๋๋ค.
์ด๋ ART ๋๋ GL ๋ ๋๋ง ์ฝํ ์ธ (๋ฐ ์ด๋ ์ ๋๋ React Native)์ ๊ฐ์ ์๋ฏธ ์ฒด๊ณ๋ฅผ ๊ฐ์ ธ์ฌ ๊ธฐ์กด ์ง์ ํธ๋ฆฌ๊ฐ ์์ ์ ์๋ ๊ฒฝ์ฐ ์ด๋ก ์ ์ธ ๊ฒ์ด ์๋๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ด ๊ฑฐํ ์ด ๋๋ ๊ณณ์ด๋ผ๊ณ ๋งํ ์ ์๋ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค.
์ผ๋ถ ์ฑ์๋ ๋ชจ๋ฌ์ ๋ชจ๋ฌ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด FB์๋ ๋ชจ๋ฌ ์์ ์์ ์ ์๋ ์ฑํ ์ฐฝ์ด ์๊ฑฐ๋ ๋ชจ๋ฌ์ด ์ฑํ ์ฐฝ์ ์ผ๋ถ์ผ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ชจ๋ฌ์กฐ์ฐจ๋ ํธ๋ฆฌ์ ์ด๋์ ์ํ๋์ง์ ๋ํ ์ปจํ ์คํธ๊ฐ ์์ต๋๋ค. ๊ทธ๊ฒ์ ๊ฒฐ์ฝ ์์ ํ ๋ ๋ฆฝ์ ์ด์ง ์์ต๋๋ค.
์ด๋ฒคํธ ๋ฒ๋ธ๋ง๊ณผ ์ปจํ ์คํธ์ ๋ํด ๋ ๊ฐ์ง ๋ค๋ฅธ ์๋ฏธ๋ฅผ ๊ฐ์ง ์ ์๋ค๋ ๋ง์ ์๋๋๋ค. ์ด๋ ์ด์ ๋ํด ๋ช ์์ ์ด๋ฉฐ ๋ค๋ฅธ ํ๋ ์์ด ํฌํธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ ๋ค ๋์ผํ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ฅด๋๋ก ๋ณด์ฅํ๋ ๊ฒ์ ๋ธ๋ผ์ฐ์ ์์์ ๋์ผํ ์ฌ์ฉ์ ๊ณต๊ฐ ์ด๋ฒคํธ์ ๋ํด ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ด ์์ ํ ๊ตฌํ๋ ์ ์์์ ์๋ฏธํ๊ธฐ ๋๋ฌธ์ ์ ๋ง ๊ฐ๋ ฅํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ด๊ฒ์ ์ค๋๋ ๋ค์ํ Redux ์ปจํ
์คํธ์์ ๋ฐ์ํฉ๋๋ค. this.context.dispatch("Hover")
๊ฐ ์ฌ์ฉ์ ๊ณต๊ฐ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ด๋ผ๊ณ ์์ํด๋ณด์ญ์์ค. ์ปจํ
์คํธ์ ์ผ๋ถ๋ก React ์ด๋ฒคํธ๋ฅผ ๊ตฌํํ ์๋ ์์ต๋๋ค. ๋ด๊ฐ ์ด๊ฒ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์
๋๋ค. ์ง๊ธ ๋ชจ๋ ๋ฉด์์ ๋น์ ๋ ํ ์ ์์ต๋๋ค. ์ด ๋ ์ปจํ
์คํธ๋ฅผ ๋ถ๊ธฐํ๋ฉด ์ผ๋ฐ ์ปจํ
์คํธ์ ๋ณ๋ ฌ๋ก DOM ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด๋ ๋ค๋ฅธ ์ฌ์ฉ์ ๊ณต๊ฐ ์ปจํ
์คํธ API๊ฐ ์์ฑ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋์ ์ฌ๋กฏ์ด ์ถฉ๋ถํ์ง ํ์ธํ๊ธฐ ์ํด ์ฝ๊ฐ ๋ฐ๋ํ๋ ์ด์ ์ ๋๋ค. ์๋ํ๋ฉด) ์ด์จ๋ ์ด๋ค ์ปจํ ์คํธ ๋ฒ๋ธ๋ง์ด ๋ฐ์ํ๋์ง ๋ช ์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. b) ์ธ๊ณ๋ฅผ ํฌํฌํ๊ณ ๋ ๊ฐ์ ์ ์ฒด ์ปจํ ์คํธ ์์คํ ์ ๊ฐ๋ ๊ฒ์ ํผํ ์ ์์ต๋๋ค.
ํนํ: ํฉ์ฑ ํฌ์ปค์ค ์ด๋ฒคํธ์์ stopPropagation์ ํธ์ถํ์ฌ ํฌํธ ๋ฐ์ผ๋ก ๋ฒ๋ธ๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ฉด stopPropagation์ด #document์ ์๋ React์ ์บก์ฒ๋ ํธ๋ค๋ฌ์ ์๋ ๋ค์ดํฐ๋ธ ํฌ์ปค์ค ์ด๋ฒคํธ์์๋ ํธ์ถ๋ฉ๋๋ค.
. ์ฐ๋ฆฌ๋ ํธ๋ค๋ฌ๋ฅผ #document๋ก ์ด๋ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง React์ ๋ฐ๊ฐ๋ฝ์ ๋ฐ์ง ์๊ธฐ ์ํด ๊ณผ๊ฑฐ์๋ ํนํ ๊ทธ๋ ๊ฒ ํ์ง ์์์ต๋๋ค.
@craigkovatch , ๋ฌธ์์ onFocusCapture
์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ์
จ์ต๋๊น? ๋ด ํด๊ฒฐ ๋ฐฉ๋ฒ์์ ์บก์ฒ๋ ์ด๋ฒคํธ๋ฅผ ์ค์งํ๋ฉด ์ ๋ฉ๋๋ค. ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ด๋ค ์กฐ์น๋ฅผ ์ทจํ๋์ง์ ๋ํ ์์ธํ ์๋ฅผ ์ ๊ณตํ ์ ์์ต๋๊น?
๋ํ ๋ด ์ฝ๋์ blur
์ด๋ฒคํธ๋ฅผ ์ค์งํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ค์งํด์๋ ์ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ด ์ง๋ฌธ์ ๋ ๊น์ด ์กฐ์ฌํ๊ณ ๋ณด๋ค ์์ ์ ์ธ ์๋ฃจ์
์ ์ฐพ๊ธฐ ์ํด ๋
ธ๋ ฅํ ๊ฒ์
๋๋ค.
@kib357 ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์ ์ํ๋ ๊ฒ์ด ์๋๋ผ React์ ๋ณ๋์ ๋ฒ๊ทธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ฌธ์ ์ ์ฝ๋๋ ๊ธฐ๋ณธ ์บก์ฒ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฌ์ฉํฉ๋๋ค(์: document.body.addEventListener('focus', handler, true)
์บก์ฒ๋ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ๋ค๋ ์ฌ์ค์ ๊ฐ์ํ ๋ @craigkovatch๋ ํฅ๋ฏธ๋กญ๊ฒ ๋ค๋ฆฝ๋๋ค. ๊ทธ๋ฌ๋ ์ ์ด๋ฐ ์ผ์ด ๋ฐ์ํ๋์ง ์๋ฌด ์๊ฐ์ด ์์ต๋๋ค.
ํฌํธ ๋ ๋๋ง์ ์ฌ์ฉํ๊ธฐ ์ํ ๋ ๊ฐ์ง ์๋๋ฆฌ์ค๊ฐ ์์ต๋๋ค.
ํ์ฌ createPortal
API๋ ์ฒซ ๋ฒ์งธ ์๋๋ฆฌ์ค๋ง ์ถฉ์กฑํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ ๋ฒ์งธ๋ก ์๋ก์ด React.render๋ฅผ ์ฌ์ฉํ๋ผ๋ ์ ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ชจ๋ ๋ ์ด์ด์ ๋ํด ๋ชจ๋ ์ ๊ณต์๊ฐ ์๋ ๋ณ๋์ ์ฑ์ ๋ง๋๋ ๊ฒ์ ๋งค์ฐ ์ข์ง ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๋ ์ถ๊ฐ ์ ๋ณด๋ ๋ฌด์์
๋๊น?
createPortal
API์์ ์ ์๋ ๋งค๊ฐ๋ณ์์ ๋จ์ ์ ๋ฌด์์
๋๊น?
@sebmarkbage ์ฌ๋กฏ API์ ๋ํ ์ฆ๊ฐ์ ์ธ ์ง๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ฌ๋ฌ SlotContents
๋ฅผ ๋์์ ํ๋์ Slot
์ ์ฝ์
ํ ์ ์์ต๋๊น? ์ธํฐํ์ด์ค์์ ์ฌ๋ฌ "ํ์
" ๋๋ "๋ชจ๋ฌ"์ ๋์์ ์ฌ๋ ๊ฒ์ ๋๋ฌธ ์ผ์ด ์๋๋๋ค. ๋ด ์๋ฒฝํ ์ธ๊ณ์์ Popup
API๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ๊ฒ์
๋๋ค.
import { App } from './app'
import { PopupSlot } from './popups'
let root = (
<div>
<App />
<PopupSlot />
</div>
)
ReactDOM.render(root, document.querySelector('#root'))
// some dark corner of our app
import { Popup } from './popups'
export function SoManyPopups () {
return <>
<Popup>My Entire</Popup>
<Popup>Interface</Popup>
<Popup>Is Popups</Popup>
</>
}
์ด์ ๋ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์์ ํ ์ฐพ์ ์ ์๋ ์๋ก์ด ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์์์ ์ ์ํ "์ด๋ฒคํธ ํธ๋ฉ" ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด React Synthetic ์ด๋ฒคํธ๋ง ํฌํธ์์ ๋ฒ๋ธ๋ง๋์ง ์๋๋ก ์ฐจ๋จ๋ฉ๋๋ค. ๊ธฐ๋ณธ ์ด๋ฒคํธ๋ ์ฌ์ ํ ๊ฑฐํ์ด ์ผ๊ณ React ์ฝ๋๋ ๋๋ถ๋ถ jQuery ์์ฉ ํ๋ก๊ทธ๋จ ๋ด๋ถ์์ ํธ์คํ
๋๋ฏ๋ก <body>
์ ์ ์ญ jQuery keyDown ํธ๋ค๋ฌ๋ ์ฌ์ ํ ์ด๋ฒคํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
์ด์ ๊ฐ์ ref๋ฅผ ํตํด Portal ๋ด๋ถ์ ๊ธฐ๋ณธ ์ปจํ ์ด๋ ์์์ event.stopPropagation ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํ๋ ค๊ณ ์๋ํ์ง๋ง ์ด๋ ํฌํธ ๋ด์ ๋ชจ๋ Synthetic ์ด๋ฒคํธ๋ฅผ ์์ ํ ๋ฌดํจํํ์ต๋๋ค. React์ ์ต์์ ๋ฆฌ์ค๋๊ฐ ์บก์ฒ ๋จ๊ณ๋ฅผ ๋ณด๊ณ ์๋ค๊ณ ์๋ชป ๊ฐ์ ํ์ต๋๋ค.
React์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ ์ธ์ ์ฌ๊ธฐ์ ๋ฌด์์ ํ ์ ์๋์ง ํ์คํ์ง ์์ต๋๋ค.
const allTheEvents: string[] = 'click contextmenu doubleclick drag dragend dragenter dragexit dragleave dragover dragstart drop mousedown mouseenter mouseleave mousemove mouseover mouseout mouseup keydown keypress keyup focus blur change input invalid submit'.split(' ');
const stop = (e: React.SyntheticEvent<HTMLElement>): void => { e.stopPropagation(); };
const nativeStop = (e: Event): void => e.stopPropagation();
const handleRef = (ref: HTMLDivElement | null): void => {
if (!ref) { return; }
allTheEvents.forEach(eventName => ref.addEventListener(eventName, nativeStop));
};
/** Prevents https://reactjs.org/docs/portals.html#event-bubbling-through-portals */
export function PortalEventTrap(children: React.ReactNode): JSX.Element {
return <div
onClick={stop}
...
ref={handleRef}
>
{children}
</div>;
}
์ด๋ ReactDOM ๋ฐ JQuery๊ฐ ์ด๊ธฐํ๋๋ ์์์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. JQuery๊ฐ ๋จผ์ ์ด๊ธฐํ๋๋ฉด JQuery์ ์ต์์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋จผ์ ์ค์น๋๋ฏ๋ก ReactDOM์ ํฉ์ฑ ํธ๋ค๋ฌ๊ฐ ์คํ๋๊ธฐ ์ ์ ์คํ๋ฉ๋๋ค.
ReactDOM๊ณผ JQuery๋ ๋ชจ๋ scroll
์ ๊ฐ์ด ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฒ๋ธ๋งํ์ง ์๋ ์ด๋ฒคํธ๊ฐ ์๋ ํ ๋ด๋ถ์ ์ผ๋ก ๋ฒ๋ธ๋ง์ ์๋ฎฌ๋ ์ด์
ํ๋ ๋จ์ผ ์ต์์ ๋ฆฌ์ค๋๋ง ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค.
@Kovensky ๋ด ์ดํด๋ jQuery๊ฐ React ๋ฐฉ์์ผ๋ก "ํฉ์ฑ ๋ฒ๋ธ๋ง"์ ์ํํ์ง ์์์ผ๋ฏ๋ก ๋จ์ผ ์ต์์ ๋ฆฌ์ค๋๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ด DOM ๊ด๋ฆฌ์๋ ํ๋๋ฅผ ๊ณต๊ฐํ์ง ์์ต๋๋ค. ๋ด๊ฐ ํ๋ ธ๋ค๋ฉด ๋น์ ์ด ์ฐธ์กฐํ๋ ๊ฒ์๋ณด๊ณ ์ถ์ต๋๋ค.
์์๋ ์ด๋ฒคํธ์ ๊ฒฝ์ฐ์
๋๋ค. ์: $(document.body).on('click', '.my-selector', e => e.stopPropagation())
.
๋ณด์ธ์. ๋๊ตฐ๊ฐ ์ฝ๋๋ฅผ ์ฌ๊ตฌ์ฑํด์ผ ํ๋ ์์์ ์ ์ํ ๋์์ธ์ผ๋ก๋ ํด๊ฒฐํ ์ ์๋ค๊ณ ๋๊ตฐ๊ฐ๊ฐ ๋์๊ฒ ํ์ ์ ์ค๋ค๋ฉด ์ด๊ฒ์ React์์ ํด๊ฒฐํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋น ๋ฅธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐพ๋ ๊ฒ ์ธ์๋ ์ํํ ์ ์๋ ์ด์ ๋ฅผ ๋ณด์ง ๋ชปํ์ต๋๋ค.
@sebmarkbage ๊ทํ์ ์ ์์ ์ด๋ฒคํธ๊ฐ ์ง๊ณ ์์ ์์๊ฒ ์ ํ๋๋ ๊ฒฝ์ฐ์๋ง ํด๊ฒฐํฉ๋๋ค. ๋๋จธ์ง ๋๋ฌด๋ ์ด๋ป์ต๋๊น?
๋ค์์ Slots ๋๋ createPortal๋ก ์ ํด๊ฒฐํ ์ ์๋ค๊ณ ์๊ฐํ๋ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค.
<Form defaultValue={fromValue}>
<more-fancy-markup />
<div>
<Field name="faz"/>
<ComplexFieldModal>
<Field name="foo.bar"/>
<Field name="foo.baz"/>
</ComplexFieldModal>
</div>
</Form>
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์๋ ์ ์ฌํ์ง๋ง ์ฝ๊ฐ ๋ค๋ฅธ ์ค์ ์ด ์๋ gif๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ์์ ๋ฐ์ํ ์ฌ์ดํธ์ ๋ํด createPortal์ ์ฌ์ฉํ์ฌ ์์ ํ๋๋ฅผ ์ฑ ๋๊ตฌ ๋ชจ์(ํธ๋ฆฌ์ ํจ์ฌ ๋ ๋์ ์์น)์ผ๋ก ์ด๋ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ์ด๋ฒคํธ๊ฐ ํ์ด์ง ์ฝํ ์ธ ๋ก ๋ค์ ๋ฒ๋ธ๋ง๋๋ ๊ฒ์ ์ํ์ง ์์ง๋ง Form ์ปจํ ์คํธ๊ฐ ํจ๊ป ๊ฐ๊ธฐ๋ฅผ ์ํฉ๋๋ค. ๋ด ๊ตฌํ btw๋ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋กฏ๊ณผ ๊ฐ์ ๊ฒ์ ๋๋ค ...
@sebmarkbage unstable_renderSubtreeIntoContainer
๋ ๊ณ์ธต ๋ด์์ ๋๋ ๋ณ๋์ ํจํค์ง ํ๋ ์์ํฌ์ ์ผ๋ถ๋ก ๊ตฌ์ฑ ์์์ ์์น์ ๊ด๊ณ์์ด ๊ณ์ธต์ ๋งจ ์์ ์ง์ ์ก์ธ์คํ ์ ์๋๋ก ํ์ฉํ์ต๋๋ค.
์ด์ ๋นํด ์ฌ๋กฏ ์๋ฃจ์ ์๋ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๋ํ ์ ์ค์ผ์ด์ค๊ฐ ์์ต๋๋ค(์ด๋ฏธ ์ธ๊ธํ ๊ฒ๊ณผ ์ ์ฌํ ์ ์์).
์ฌ์ฉ์๊ฐ "์ฌ๊ฐ๋ฏธ"๋ก ๋ง์ฐ์ค๋ก ๋ฌผ๊ฑด์ ์ ํํ ์ ์๋ ํ๋ฉด์ด ์์ต๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก 100% ๋๋น/๋์ด์ด๋ฉฐ ๋ด ์ฑ์ ๋ฃจํธ์ ์์ผ๋ฉฐ onMouseDown
์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ํ๋ฉด์๋ ๋ชจ๋ฌ ๋ฐ ๋๋กญ๋ค์ด๊ณผ ๊ฐ์ ํฌํธ์ ์ฌ๋ ๋ฒํผ๋ ์์ต๋๋ค. ํฌํธ ๋ด๋ถ์ mouseDown ์ด๋ฒคํธ๋ ์ค์ ๋ก ์ฑ ๋ฃจํธ์ ์ฌ๊ฐ๋ฏธ ์ ํ ๊ตฌ์ฑ ์์์ ์ํด ๊ฐ๋ก์ฑ์ด์ง๋๋ค.
๋๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง์ ๊ฒ์ ๋ณธ๋ค:
ํ์ฌ ๋ด ์๋ฃจ์ ์ ์ด๋ฒคํธ๋ฅผ ํํฐ๋งํ๋ ๊ฒ์ ๋๋ค.
const appRootNode = document.getElementById('root');
const isInPortal = element => isNodeInParent(element, appRootNode);
handleMouseDown = e => {
if (!isInPortal(e.target)) {
return;
}
...
};
์ด๊ฒ์ ๋ถ๋ช ํ ์ฐ๋ฆฌ ๋ชจ๋์๊ฒ ์ต์์ ์๋ฃจ์ ์ด ์๋๋ฉฐ ์ค์ฒฉ๋ ํฌํธ์ด ์๋ ๊ฒฝ์ฐ ๊ทธ๋ค์ง ์ข์ง ์์ ๊ฒ์ด์ง๋ง ํ์ฌ ์ฌ์ฉ ์ฌ๋ก(ํ์ฌ ์ ์ผํ ์ฌ์ฉ ์ฌ๋ก)์์๋ ์๋ํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์๋ก์ด ์ปจํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋ณต์กํ ๋ฆฌํฉํฐ๋ง์ ์ํํ๊ณ ์ถ์ง ์์ต๋๋ค. ๋ด ์๋ฃจ์ ์ ๊ณต์ ํ๊ณ ์ถ์์ต๋๋ค.
์ด ์ค๋ ๋์ ๋ค๋ฅธ ๊ณณ์์ ์ธ๊ธํ ๋๋ก ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ์ฐจ๋จ์ ์ํํ ์ ์์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ด๊ฐ ๊ฒช๊ณ ์๋ ๋ ๋ค๋ฅธ ๊ฐ์์ ์ธ ๋ฌธ์ ๋ ๋ฒ๋ธ๋ง๋์ง ์๋ onMouseEnter
SyntheticEvent์
๋๋ค. ๋์ ์ฌ๊ธฐ์ ์ค๋ช
๋ ๋๋ก from
๊ตฌ์ฑ ์์์ ๊ณตํต ๋ถ๋ชจ์์ to
๊ตฌ์ฑ ์์๋ก ์ด๋ ํฉ๋๋ค . ์ฆ, ๋ง์ฐ์ค ํฌ์ธํฐ๊ฐ ๋ธ๋ผ์ฐ์ ์ฐฝ ์ธ๋ถ์์ ๋ค์ด์ค๋ฉด DOM ์๋จ์์ createPortal์ ๊ตฌ์ฑ ์์๊น์ง ๋ชจ๋ onMouseEnter
ํธ๋ค๋ฌ๊ฐ ํด๋น ์์๋ก ํธ๋ฆฌ๊ฑฐ๋์ด ๋ชจ๋ ์ข
๋ฅ์ ์ด๋ฒคํธ๊ฐ ์ด๋ฅผ ๋ฐ์์ํต๋๋ค. unstable_renderSubtreeIntoContainer
์ ์ด ์์ต๋๋ค. onMouseEnter
๋ ๋ฒ๋ธ๋ง๋์ง ์๊ธฐ ๋๋ฌธ์ Portal ์์ค์์ ์ฐจ๋จํ ์ ์์ต๋๋ค. ( onMouseEnter
์ด๋ฒคํธ๋ ๊ฐ์ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์กด์คํ์ง ์๊ณ ๋ณธ๋ฌธ ๋ด์ฉ์ ํตํด ์์๋ฅผ ์ง์ ํ์ง ์๊ณ ํ์ ํธ๋ฆฌ๋ก ์ง์ ๋ด๋ ค๊ฐ๊ธฐ ๋๋ฌธ์ unstable_renderSubtreeIntoContainer
์์๋ ๋ฌธ์ ๊ฐ ๋์ง ์์์ต๋๋ค.)
onMouseEnter
์ด๋ฒคํธ๊ฐ DOM ๊ณ์ธต์ ๋งจ ์์์ ์ ํ๋๊ฑฐ๋ ํฌํธ ํ์ ํธ๋ฆฌ๋ก ์ง์ ์ ํ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ด๋์ด๊ฐ ์๋ ์ฌ๋์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ญ์์ค.
@JasonGore ๋๋ ๋ํ์ด ๋์์ ๋ฐ๊ฒฌํ์ต๋๋ค.
์๋ฅผ ๋ค์ด.
div๊ฐ onMouseOver๋ฅผ ํธ๋ฆฌ๊ฑฐํ ๋ ๋ ๋๋ง๋๋ ์ปจํ ์คํธ ๋ฉ๋ด๊ฐ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฉ๋ด์ ํญ๋ชฉ ์ค ํ๋๋ฅผ ํด๋ฆญํ์ฌ createPortal๋ก ๋ชจ๋ฌ์ ์ฝ๋๋ค. ๋ธ๋ผ์ฐ์ ์ฐฝ ๋ฐ์ผ๋ก ๋ง์ฐ์ค๋ฅผ ๊ฐ์ ธ์ค๋ฉด onMouseLeave ์ด๋ฒคํธ๊ฐ ์ปจํ ์คํธ ๋ฉ๋ด๋ก ์ ํ๋์ด ์ปจํ ์คํธ ๋ฉ๋ด(๋ฐ๋ผ์ ๋ชจ๋ฌ)๊ฐ ๋ซํ๋๋ค...
์ ์ฒด๋ฅผ ํด๋ฆญํ ์ ์๊ธฐ๋ฅผ ์ํ์ง๋ง(๋งํฌ๋ก) ๋ชฉ๋ก ํญ๋ชฉ์ด ์์์ง๋ง ํ์ธ์ ์ํด ๋ชจ๋ฌ์ ์ฌ๋ ์ด๋ฆ ์๋ ๋ ์ด๋ธ์ ์ญ์ ๋ฒํผ์ ์ํ๋ ๋์ผํ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
๋ด ์ ์ผํ ํด๊ฒฐ์ฑ ์ ๋ค์๊ณผ ๊ฐ์ด ๋ชจ๋ฌ div์์ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํ๋ ๊ฒ์ ๋๋ค.
// components/Modal.js
onClick(e) {
e.stopPropagation();
}
return createPortal(
<div onClick={this.onClick} ...
...
๋ชจ๋ ๋ชจ๋ฌ์์ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํ ์ ์์ง๋ง ์์ง ๊ทธ๋ฐ ์ผ์ด ์ผ์ด๋๊ธธ ์ํ๋ ๊ฒฝ์ฐ๊ฐ ์์ผ๋ฏ๋ก ์ ์๊ฒ ํจ๊ณผ์ ์ ๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์ ์ ์ฌ์ ์ธ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
@jnsandrew ~ 50๊ฐ์ง ๋ค๋ฅธ ์ด๋ฒคํธ ์ ํ์ด ์๋ค๋ ๊ฒ์ ์์ง ๋ง์ธ์ ๐
์ด๊ฒ๋ง ์น์ธ์. React๊ฐ DOM ์ด๋ฒคํธ ๋ฒ๋ธ๋ง๊ณผ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์๋ํ๋ค๋ ๊ฒ์ด ์ ์๊ฒ๋ ์ด์ํด ๋ณด์ ๋๋ค.
์ด๊ฒ์ +1. ์ฐ๋ฆฌ๋ React.createPortal
๋ฅผ ์ฌ์ฉํ์ฌ iframe ๋ด๋ถ์์ ๋ ๋๋งํ๊ณ ์์ผ๋ฉฐ(์คํ์ผ ๋ฐ ์ด๋ฒคํธ ๊ฒฉ๋ฆฌ ๋ชจ๋์ ๋ํด) ์ด๋ฒคํธ๊ฐ ์์ ๋ฐ์ผ๋ก ๋ฒ๋ธ๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์๋ค๋ ๊ฒ์ ํฐ ๋ฌธ์ ์
๋๋ค.
์ด๊ฒ์ React์ ๋ฐฑ๋ก๊ทธ์์ 12๋ฒ์งธ๋ก ๋ง์ด ์ถ์ฒ๋ ๋ฌธ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ์ ์ด๋ ๋ฌธ์๋ ๊ทธ๊ฒ์ ๋ํด ์ด๋ ค ์์ต๋๋ค https://reactjs.org/docs/portals.html#event -bubbling-through-portals - ๊ทธ๋ค์ ๋จ์ ์ด๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ธ๊ธํ์ง ์๊ณ ๋์ "๋ ์ ์ฐํ ์ถ์ํ๋ฅผ ํ์ฉํฉ๋๋ค. ":
๋ฌธ์๋ ์ด๊ฒ์ด ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์์ ์ค๋ช ํ๊ณ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ์ํด์ผ ํฉ๋๋ค. ์ ๊ฒฝ์ฐ์๋ https://github.com/reactjs/react-modal์ ์ฌ์ฉํ๋ ๋งค์ฐ ๊ฐ๋จํ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค. ๋๋กญ๋ค์ด๊ณผ ๊ฐ์ ํญ๋ชฉ์ ์ฌ๋ ๋ฒํผ์ด ์์ผ๋ฉฐ ๊ทธ ์์ ๋ชจ๋ฌ์ ์์ฑํ๋ ๋ฒํผ์ด ์์ต๋๋ค. ๋ชจ๋ฌ ๋ฒ๋ธ์ ์๋จ ๋ฒํผ์ผ๋ก ํด๋ฆญํ๋ฉด ์์น ์๋ ์์ ์ ์ํํฉ๋๋ค. ๋ชจ๋ฌ์ ์์ง๋ ฅ ์๋ ๊ตฌ์ฑ ์์๋ก ์บก์ํ๋๊ณ ํฌํธ ๋ถ๋ถ์ ๋นผ๋ด๋ฉด ํด๋น ์บก์ํ๊ฐ ๊นจ์ง๊ณ ์ถ์ํ๊ฐ ๋์ถ๋ฉ๋๋ค. ํ ๊ฐ์ง ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ชจ๋ฌ์ด ์ด๋ ค ์๋ ๋์ ์ด๋ฌํ ๋ฒํผ์ ๋นํ์ฑํํ๋๋ก ํ๋๊ทธ๋ฅผ ๋ค์ง๋ ๊ฒ์ ๋๋ค. ๋ฌผ๋ก ์์์ ์ ์ํ ๋๋ก ์ ํ๋ฅผ ์ค์งํ ์๋ ์์ต๋๋ค. ์ด๋ค ๊ฒฝ์ฐ์๋ ๊ทธ๋ ๊ฒ ํ๊ณ ์ถ์ง ์์ ์๋ ์์ต๋๋ค.
๋ฒ๋ธ๋ง ๋ฐ ์บก์ฒ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ผ๋ง๋ ๋์์ด ๋๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค(React๊ฐ ๋ด๋ถ์์ ๋ฒ๋ธ๋ง์ ์์กดํ๋ค๋ ๊ฒ์ ์๊ณ ์์). ํ์คํ ์คํ ๋ฆฌ๊ฐ ์์ง๋ง ์ฝ๋ฐฑ์ ์ ๋ฌํ๊ฑฐ๋ ๋ณด๋ค ๊ตฌ์ฒด์ ์ธ ์ด๋ฒคํธ(์: redux action) ๋ฒ๋ธ ์ ๋๋ ์บก์ฒ ๋ค์ด๋ณด๋ค ๋ถํ์ํ ์ค๊ฐ์์ ๋ฌด๋ฆฌ๋ฅผ ํตํด ๊ทธ๋ฌํ ์ผ์ ํ ์ ์์ต๋๋ค. https://css-tricks.com/dangers-stopping-event-propagation/ ๊ณผ ๊ฐ์ ๊ธฐ์ฌ๊ฐ ์์ผ๋ฉฐ ์ ๋ ์ฃผ๋ก "์ธ๋ถ"๋ฅผ ํด๋ฆญํ ๋ ํญ๋ชฉ์ ๋ซ๊ธฐ ์ํด ์ ์ฒด๋ก์ ์ ํ์ ์์กดํ๋ ์ฑ์์ ์์ ํ์ง๋ง ์ฐจ๋ผ๋ฆฌ ๋ชจ๋ ๊ฒ ์์ ๋ณด์ด์ง ์๋ ์ค๋ฒ๋ ์ด๋ฅผ ๋๊ณ ํด๋ฆญํ๋ฉด ๋ซ์ต๋๋ค. ๋ฌผ๋ก ์ด๋ฐ ๋ณด์ด์ง ์๋ ์ค๋ฒ๋ ์ด๋ฅผ ๋ง๋ค๊ธฐ ์ํด React์ Portal์ ์ฌ์ฉํ ์๋ ์์์ง๋ง...
์ฌ๊ธฐ์๋ ์ ์ง ๊ด๋ฆฌ์ ์ ๋ชฝ๋ ์์ต๋๋ค. ์ ์ด๋ฒคํธ๊ฐ DOM์ ์ถ๊ฐ๋๋ฉด ์์์ ๋ ผ์ํ ๊ธฐ์ ๋ก "๋ด์ธ๋" ํฌํธ์ ์ ์ง ๊ด๋ฆฌ์๊ฐ (๊ด๋ฒ์ํ) ๋ธ๋๋ฆฌ์คํธ์ ์ถ๊ฐํ ์ ์์ ๋๊น์ง ์ ์ด๋ฒคํธ๋ฅผ "๋์ถ" ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ์ ํด๊ฒฐํด์ผ ํ ์ฃผ์ ์ค๊ณ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๊ต์ฐจ ํฌํธ ๋ฒ๋ธ๋ง์ ์ตํธ์ธ ๋๋ ์ตํธ์์ํ๋ ๊ธฐ๋ฅ์ ์ฌ์ ํ โโ๋์๊ฒ ์ต๊ณ ์ API ์ต์ ์ผ๋ก ๋ณด์ ๋๋ค. ๊ตฌํ์ ์ด๋ ค์์ ํ์คํ์ง ์์ง๋ง 1๋ ์ด ์ง๋ ํ์๋ Tableau์์ ์ด์ ๊ด๋ จ๋ ํ๋ก๋์ ๋ฒ๊ทธ๊ฐ ๊ณ์ ๋ฐ์ํ๊ณ ์์ต๋๋ค.
๋ชจ๋ฌ์ ๋ด ์์์ด ๋ค๋ฅธ ์์์ ์ ์ถํ ์ด์ ๋ฅผ ์์๋ณด๊ธฐ ์ํด 2์๊ฐ์ ๋ณด๋ด์ญ์์ค.
๋ง์นจ๋ด ๋๋ ๊ทธ ๋ฌธ์ ๋๋ถ์ ๊ทธ๊ฒ์ ์์ ๋์ต๋๋ค!
๋๋ onSubmit
์ ํ๊ฐ ํ์ํ ๋๋ฅผ ์๊ธฐ ์ํด ์ ๋ง ๊ณ ๊ตฐ๋ถํฌํฉ๋๋ค. ๊ธฐ๋ฅ๋ณด๋ค๋ ๋ฒ๊ทธ์ ๋ ๊ฐ๊น์ต๋๋ค.
์ต์ํ ๋ฐ์ ๋ฌธ์์ ๊ฒฝ๊ณ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ด ๊ฐ์:
ํฌํธ์ ํตํ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ํ๋ฅญํ ๊ธฐ๋ฅ์ด์ง๋ง ์ผ๋ถ ์ด๋ฒคํธ ์ ํ๋ฅผ ๋ฐฉ์งํ๋ ค๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. onSubmit={(e) => {e.stopPropagation()}}
๋ฅผ ์ถ๊ฐํ์ฌ ์ด๋ฅผ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
์ด๊ฒ๋ +1. ์ฐ๋ฆฌ๋ ๋ชจ๋ฌ์ ๋ณด์ฌ์ฃผ๋ ํด๋ฆญ ๊ฐ๋ฅํ ํ ์คํธ์ ํจ๊ป draftjs๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํฌ์ปค์ค, ์ ํ, ๋ณ๊ฒฝ, ํค ๋๋ฅด๊ธฐ์ ๊ฐ์ ๋ชจ๋ฌ์ ๋ชจ๋ ์ด๋ฒคํธ๋ ์ค๋ฅ๋ก draftjs๋ฅผ ํญ๋ฐ์ํต๋๋ค.
IMO, ์ด๋ฒคํธ ํ๋ก์ ๋์์ ๊ทผ๋ณธ์ ์ผ๋ก ์์๋์์ง๋ง(๋์๊ฒ๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํจ) ์ด๊ฒ์ด ๋ ผ๋์ ์ฌ์ง๊ฐ ์์์ ์๊ณ ์์ต๋๋ค. ์ด ์ค๋ ๋๋ ์ปจํ ์คํธ๊ฐ ์๋ ์ด๋ฒคํธ๊ฐ ์๋ ์ปจํ ์คํธ ๋ฅผ ์ํํ๋ ํฌํธ์ด ํ์ํ๋ค๋ ๊ฒ์ ๊ฐ๋ ฅํ๊ฒ ์ ์ ํฉ๋๋ค . ํต์ฌ ํ์ด ๋์ํฉ๋๊น? ์ด๋ ์ชฝ์ด๋ , ์ฌ๊ธฐ์์ ๋ค์ ๋จ๊ณ๋ ๋ฌด์์ ๋๊น?
ํฌํธ์์ ์ด๋ฒคํธ๋ฅผ ์ ํํ๋ ๊ฒ์ด ์๋๋ ๋์์ธ ์ด์ ๋ฅผ ์ ๋ง ์ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์ ํ์ ์ฃผ์ ๊ฐ๋ ์ ์์ ํ ๋ฐ๋๋ฉ๋๋ค. ๋๋ ํฌํธ์ด ์ด๋ฐ ์ข ๋ฅ์ ์ผ(์๋ ์ค์ฒฉ, ์ด๋ฒคํธ ์ ํ ๋ฑ)์ ํผํ๊ธฐ ์ํด ์ ํํ ๋ง๋ค์ด์ก๋ค๊ณ ์๊ฐํ์ต๋๋ค.
์์ ํธ๋ฆฌ ๊ทผ์ฒ์ ํฌํธ์ ๋ฐฐ์นํ๋ฉด ์ด๋ฒคํธ๊ฐ ์ ํ๋๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
class SomeComponent extends React.Component<any, any> {
render() {
return <>
<div className="some-tree">
// Portal here will bubble events
</div>
// Portal here will also bubble events, just checked
</>
}
}
์ด ๊ธฐ๋ฅ ์์ฒญ์ ๋ํด +1
DOM์์ ์ด๋ฒคํธ๋ DOM ํธ๋ฆฌ๋ฅผ ๋ฒ๋ธ๋งํฉ๋๋ค. React์์ ์ด๋ฒคํธ๋ ๊ตฌ์ฑ ์์ ํธ๋ฆฌ๋ฅผ ๋ฒ๋ธ๋งํฉ๋๋ค.
์ ๋ ๊ธฐ์กด ๋์์ ์๋นํ ์์กดํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ค์ฒฉ๋ ์ ์๋ ํ์
์ด ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ๋ชจ๋ overflow: hidden
๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํ ํฌํธ์ด์ง๋ง ํ์์์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋ ค๋ฉด ํ์์ ๊ตฌ์ฑ์์์ ๋ํ ์ธ๋ถ ํด๋ฆญ์ ๊ฐ์งํด์ผ ํฉ๋๋ค(๋ ๋๋ง๋ DOM ์์ ์ธ๋ถ์ ํด๋ฆญ ๊ฐ์ง์ ๋ค๋ฆ) . ๋ ์ข์ ์๊ฐ ์์ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์์ ํ๋ฐํ ๋
ผ์๋ฅผ ํตํด ๋ ๊ฐ์ง ํ๋์ createPortal
๋ "์ผ๋ฐ DOM" ์ปจํ
์ด๋ ๋
ธ๋ ๋ด๋ถ์ React ๊ตฌ์ฑ ์์๋ฅผ ๋ ๋๋งํ๊ธฐ ๋๋ฌธ์ React์ ํฉ์ฑ ์ด๋ฒคํธ๊ฐ Portal์์ ์ผ๋ฐ DOM ํธ๋ฆฌ ์๋ก ์ ํ๋๋ ๊ฒ์ ์๋ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
Portal์ด ์ถ์๋ ์ง ์ค๋๋์๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ ๋์์ "ํฌํธ ๊ฒฝ๊ณ๋ฅผ ๋์ด ์ ํํ์ง ์์"์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ์๋ ๋๋ฌด ๋ฆ์์ ๊ฒ์ ๋๋ค.
์ง๊ธ๊น์ง ๋ชจ๋ ๋ ผ์๋ฅผ ๋ฐํ์ผ๋ก, ๋ด ๊ฐ๋จํ ์ ์์ (์ฌ์ ํ)์ ๋๋ค : createPortal์ ์ต์ ํ๋๊ทธ๋ฅผ ์ถ๊ฐ ๊ฒ์ ๋ฐฉ์ง ํฌํธ ๊ฒฝ๊ณ ๊ณผ๊ฑฐ์ ์ด๋ค ์ด๋ฒคํธ ์ ํ.
๋ ๊ฐ๋ ฅํ ๊ฒ์ ๊ฒฝ๊ณ๋ฅผ "ํ์ง"ํ๋ ๊ฒ์ ํ์ฉํด์ผ ํ๋ ์ด๋ฒคํธ์ ํ์ดํธ๋ฆฌ์คํธ๋ฅผ ์ ๊ณตํ๋ ๋์์ ๋๋จธ์ง๋ ์ค์งํ๋ ๊ธฐ๋ฅ์ผ ์ ์์ต๋๋ค.
@gaearon React ํ์ด ์ค์ ๋ก ์ด๊ฒ์ ์ํํ ์ ์๋ ์์ ์ ์์ต๋๊น? ์ด๊ฒ์ ์์ 10๊ฐ ๋ฌธ์ ์ด์ง๋ง ๊ฝค ์ค๋ซ๋์ ์ด์ ๋ํด ์๋ฌด ์์๋ ๋ฃ์ง ๋ชปํ์ต๋๋ค.
์ด์ ๋ํ ์ง์์ ์ถ๊ฐํ๊ณ ์ถ์ต๋๋ค. React ์ปจํ ์คํธ์ DOM ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ๋ชจ๋ ํฌํธ๋งํ๋ ๊ฒ์ด ์ปจํ ์คํธ๋ง ํฌํธ๋งํ๋ ๊ฒ๋ณด๋ค ๊ฐ๋ ์ ์ผ๋ก ๋ ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ์ฃผ์ฅํ๋ ์๋ ์ @sebmarkbage ์๊ฒฌ์ ๋์ํ์ง ์์ต๋๋ค.
DOM์ ํ ์์น์์ ๋ค๋ฅธ ์์น๋ก ์ปจํ ์คํธ๋ฅผ ํฌํธํ๋ ๊ธฐ๋ฅ์ ๋๊ตฌ ์ค๋ช , ๋๋กญ๋ค์ด, ํธ๋ฒ ์นด๋ ๋ฐ ๋ํ ์์์ ๊ฐ์ ๋ชจ๋ ๋ฐฉ์์ ์ค๋ฒ๋ ์ด๋ฅผ ๊ตฌํํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ๋ฐฉ์์ . ์ปจํ ์คํธ๋ React ๊ฐ๋ ์ด๋ฏ๋ก ์ด ๋ฉ์ปค๋์ฆ์ React ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋ฐ๋ฉด์ DOM ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ DOM์ ํ ์์น์์ ๋ค๋ฅธ ์์น๋ก ํฌํธํ๋ ๊ธฐ๋ฅ์ DOM ๊ตฌ์กฐ๊ฐ ๋ช ์์ ์ผ๋ก ์ค์ ํ ๊ฒ๊ณผ ๋ค๋ฅธ ๊ฒ์ฒ๋ผ ๊ฐ์ฅํ ์ ์๋ ๋ฉ์ง ํธ๋ฆญ์ ๋๋ค. ์ด๊ฒ์ DOM์ ๋ค๋ฅธ ๋ถ๋ถ์ ์์ํ๋ ค๋ ๊ฒฝ์ฐ ์์์ ์ํด DOM ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ฌ์ฉํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ์ค๋ฒ๋ ์ด ๋ด๋ถ์์ ์ธ๋ถ๋ก ๋ฒ๋ธ๋ง๋๋ DOM ์ด๋ฒคํธ์ ์์กดํ๊ธฐ๋ณด๋ค๋ React๊ฐ ์๋ ๊ฒฝ์ฐ ์ด์จ๋ ์ฝ๋ฐฑ(๋๋ ์ปจํ ์คํธ)์ ์ฌ์ฉํด์ผ ํ ๊ฒ์ ๋๋ค. ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ง์ ํ๋ฏ์ด ์๋์ ์ด๋ ๋น์๋์ ์ด๋ ์ค๋ฒ๋ ์ด ๋ด๋ถ์์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ "์ ๊ทผ"ํ๊ณ ์ฒ๋ฆฌํ๊ณ ์ถ์ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์์ต๋๋ค.
DOM ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ฃผ๋ก DOM ์ด๋ฒคํธ๋ฅผ DOM ๋์๊ณผ ์ผ์น์ํค๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋ชจ๋ ํด๋ฆญ์ ์ค์ ๋ก ์ ์ฒด ์ค์ฒฉ ์์ ์งํฉ์ ๋ํ ํด๋ฆญ์ ๋๋ค. ๊ตฌ์ฑ ์์๊ฐ DOM์ ์์ธก ๊ฐ๋ฅํ ๋นํธ๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์์ ๊ฐ์ธ ๋์ฐ๋ฏธ ๊ตฌ์ฑ ์์๊ฐ ์๋ ํ ๋์ ์์ค์ ์์ ๋ฉ์ปค๋์ฆ์ธ IMO๋ก ๊ฐ์ฃผ๋์ง ์์ผ๋ฉฐ DOM ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ์ฌ React ๊ตฌ์ฑ ์์ ๊ฒฝ๊ณ๋ฅผ ๋์ด ์์ํ๋ ๊ฒ์ ํ๋ฅญํ ์บก์ํ๊ฐ ์๋๋๋ค.
event.target === event.currentTarget์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ํ์ง๋ง ์ด๊ฒ์ ์ ๋ง ๋จธ๋ฆฌ๊ฐ ์ํ๋ค.
์ด ๋นํธ ๋๋ฅผ ์ค๋ ์ฌ์ฉ ํ ์ค๋ฒ ๊ตฌ์ฑ ์์ ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ๋์ unstable_renderSubtreeIntoContainer
์ฌ์ฉํ๊ธฐ createPortal
. ๋ฌธ์ ์ ๊ตฌ์ฑ ์์์๋ ๋๋๊ทธ ๊ฐ๋ฅํ ์์๊ฐ ํฌํจ๋์ด ์์ผ๋ฉฐ ๋ค๋ฅธ ๋๋๊ทธ ๊ฐ๋ฅํ ์์์ ํ์ ์์๋ก ๋ ๋๋ง๋ฉ๋๋ค. ์ด๋ ์์ ์์์ ํ์ค๋ฒ ์์ ๋ชจ๋์ ๋ง์ฐ์ค ๋ฐ ํฐ์น ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํฌํจ๋์ด ์์ผ๋ฉฐ ํฌํธ์ ํ์ค๋ฒ์ ์ํธ ์์ฉํ ๋ ๋ ๋ค ์คํ๋๊ธฐ ์์ํ์์ ์๋ฏธํฉ๋๋ค.
unstable_renderSubtreeIntoContainer
๊ฐ ๋ ์ด์ ์ฌ์ฉ๋์ง ์๊ธฐ ๋๋ฌธ์ (?) ๋์ฒด ์๋ฃจ์
์ด ํ์ํฉ๋๋ค. ์์ ์ ์๋ ํด๊ฒฐ ๋ฐฉ๋ฒ ์ค ์ด๋ ๊ฒ๋ ์คํ ๊ฐ๋ฅํ ์ฅ๊ธฐ ์๋ฃจ์
์ผ๋ก ๋ณด์ด์ง ์์ต๋๋ค.
์ด๋ด! ์ด ๋ชจ๋ ์ ์์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
๋ด ๋ฌธ์ ์ค ํ๋๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด๋์์ต๋๋ค.
React ํ ์ ์ค์์ฑ๊ณผ ๋ฅ๋ ฅ์ ๋ํ ํ๋ฅญํ๊ณ ์ ์ตํ ๊ธฐ์ฌ๋ฅผ ์ฝ๊ณ ์ถ์ต๋๊น? ๊ฐ๋ฐ์ ๊ด์ฌ์ด ์๋ ๋ชจ๋ ๋ถ๋ค์๊ฒ ์ ์ฉํ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ด์ ๋น๋๋ค!
IMO๋ ํฌํธ์์ ์ปจํ
์คํธ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํ์ง๋ง ์ด๋ฒคํธ๋ฅผ ๋ฒ๋ธ๋งํ์ง ์๊ธฐ๋ฅผ ์ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ ๋ง์ต๋๋ค. Angular 1.x๋ฅผ ์ฌ์ฉํ ๋ $scope
๋ฐ ํ
ํ๋ฆฟ ๋ฌธ์์ด์ ์ฌ์ฉํ์ฌ ํด๋น ํ
ํ๋ฆฟ์ ์ปดํ์ผ/๋ ๋๋งํ๊ณ ๋ณธ๋ฌธ์ ์ถ๊ฐํ๋ ์์ฒด ํ์
์๋น์ค๋ฅผ ์์ฑํ์ต๋๋ค. ์ฐ๋ฆฌ๋ ํด๋น ์๋น์ค๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ๋ชจ๋ ํ์
/๋ชจ๋ฌ/๋๋กญ๋ค์ด์ ๊ตฌํํ์ผ๋ฉฐ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ด ์๋ ๊ฒ์ ํ ๋ฒ๋ ๋์น ์ ์ด ์์ต๋๋ค.
stopPropagation()
ํด๊ฒฐ ๋ฐฉ๋ฒ ์ window
๊ธฐ๋ณธ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค(์ด ๊ฒฝ์ฐ react-dnd-html5-backend
์ ์ํด ์ถ๊ฐ๋จ).
๋ค์์ ๋ฌธ์ ์ ๋ํ ์ต์ํ์ ์ฌํ์ ๋๋ค. https://codepen.io/mogel/pen/xxKRPbQ
ํฌํธ ์ ์ฒด์์ ํฉ์ฑ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ ๊ณํ์ด ์๋ ๊ฒฝ์ฐ ๋๊ตฐ๊ฐ๊ฐ ๊ธฐ๋ณธ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ค๋จํ์ง ์๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๊ฐ์ง๊ณ ์์ต๋๊น?
stopPropagation() ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐฝ์ ๊ธฐ๋ณธ ์ด๋ฒคํธ ์์ ๊ธฐ๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๊ฒ์ผ๋ก ๋ํ๋ฉ๋๋ค.
์ณ์. :(
ํฌํธ ์ ์ฒด์์ ํฉ์ฑ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ ๊ณํ์ด ์๋ ๊ฒฝ์ฐ
ํต์ฌ ํ์ ์นจ๋ฌต์๋ ๋ถ๊ตฌํ๊ณ ๋์ ์ด ์ค๋ ๋์ ๋ค๋ฅธ ๋ง์ ์ฌ๋๋ค์ ๊ทธ๋ฌํ ๊ณํ์ด _์ ๋ง ํฌ๋งํฉ๋๋ค_.
์๋ง๋ ๋๊ตฐ๊ฐ๊ฐ ๊ธฐ๋ณธ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ค๋จํ์ง ์๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๊ฐ์ง๊ณ ์์ต๋๊น?
์ฐ๋ฆฌ ํ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด ๋์ ๋๋ ๋ฌธ์ ๋๋ฌธ์ ํฌํธ์ ์์ ํ ๊ธ์งํ๋ ๊ฒ์ด์์ต๋๋ค. ์ฑ์ ๋ค๋ฅธ ์ปจํ ์คํธ ๋ด์ ์๋ ์ปจํ ์ด๋์ ํํฌ๊ฐ ์๋ ์ฐฝ์ ์ ๊ณตํ๋ฏ๋ก ๋ฃจํธ ์์ค ์ปจํ ์คํธ๋ฅผ ๋ฌด๋ฃ๋ก ์ป์ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์๋์ผ๋ก ์ ๋ฌํ๋ ๋ค๋ฅธ ๋ชจ๋ ๊ฒ. ์ข์ง๋ ์์ง๋ง ๋ฌด์๋ฏธํ ๋๋์ง ๋๋ฆฌ๊ธฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ณด๋ค ๋ซ์ต๋๋ค.
ํต์ฌ ํ์ ๋๊ตฐ๊ฐ ๊ฐ ๋ง์ง๋ง์ผ๋ก ์๋ต ํ ์ง 17๊ฐ์์ด ์ง๋ฌ์ต๋๋ค. ์๋ง๋ ping์ด ์ด ๋ฌธ์ ์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ผ ์ ์์ ๊ฒ์ ๋๋ค :) @sebmarkbage ๋๋ @gaearon
์ฐ๋ฆฌ ํ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด ๋์ ๋๋ ๋ฌธ์ ๋๋ฌธ์ ํฌํธ์ ์์ ํ ๊ธ์งํ๋ ๊ฒ์ด์์ต๋๋ค. ์ฑ์ ๋ค๋ฅธ ์ปจํ ์คํธ ๋ด์ ์๋ ์ปจํ ์ด๋์ ํํฌ๊ฐ ์๋ ์ฐฝ์ ์ ๊ณตํ๋ฏ๋ก ๋ฃจํธ ์์ค ์ปจํ ์คํธ๋ฅผ ๋ฌด๋ฃ๋ก ์ป์ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์๋์ผ๋ก ์ ๋ฌํ๋ ๋ค๋ฅธ ๋ชจ๋ ๊ฒ. ์ข์ง๋ ์์ง๋ง ๋ฌด์๋ฏธํ ๋๋์ง ๋๋ฆฌ๊ธฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ณด๋ค ๋ซ์ต๋๋ค.
๊ณ๋จ์ ์ํ์ ์์กดํ์ง ์๊ณ ์ํ์ ํตํด "๊ฐ์ง ํฌํธ"๋ก ์ปจํ ์คํธ๋ฅผ ์ ๋ฌํ๋ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์๊ฐํ ์ ์์ต๋๋ค.
https://github.com/reakit/reakit ์์ ์ด ๋ฌธ์ ์ ๊ด๋ จ๋ ์๋ง์ ๋ฒ๊ทธ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋๋ React Portal์ ๋ง์ด ์ฌ์ฉํ๋ฉฐ ํฌํธ์์ ์์ ๊ตฌ์ฑ ์์๋ก ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ํ๋ ๋จ์ผ ์ฌ๋ก๋ฅผ ์๊ฐํ ์ ์์ต๋๋ค.
๋ด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ถ๋ชจ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด์์ ํ์ธํ๋ ๊ฒ์ ๋๋ค.
event.currentTarget.contains(event.target);
๋๋ ๋์ ๊ธฐ๋ณธ ์ด๋ฒคํธ ์ฌ์ฉ:
const onClick = () => {};
React.useEffect(() => {
ref.current.addEventListener("click", onClick);
return () => ref.current.removeEventListener("click", onClick);
});
๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ค ์ค ๋๊ตฌ๋ ์ด์์ ์ด์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์คํ ์์ค ๊ตฌ์ฑ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด ๊ตฌ์ฑ ์์์ ์ด๋ฒคํธ ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ ์ดํ ์ ์์ต๋๋ค.
์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ๋นํ์ฑํํ๋ ์ต์ ์ ์ด๋ฌํ ๋ชจ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ ๋๋ค.
๋๋ window
์ด๋ฒคํธ์ ํด๋ก ์ ๋ค์ ํธ๋ฆฌ๊ฑฐํ๋ฉด์ React ๋ฒ๋ธ๋ง์ ์ฐจ๋จํ๋ ๋ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ ์ ํจ๊ป ํดํนํ์ต๋๋ค. OSX์ Chrome, Firefox ๋ฐ Safari์์ ์๋ํ๋ ๊ฒ์ผ๋ก ๋ณด์ด์ง๋ง IE11์ event.target
๋ฅผ ์๋์ผ๋ก ์ค์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ธ๋ฉ๋๋ค. ์ง๊ธ๊น์ง๋ ๋ง์ฐ์ค, ํฌ์ธํฐ, ํค๋ณด๋ ๋ฐ ํ ์ด๋ฒคํธ์๋ง ๊ด์ฌ์ด ์์ต๋๋ค. ๋๋๊ทธ ์ด๋ฒคํธ๋ฅผ ๋ณต์ ํ ์ ์๋์ง ํ์คํ์ง ์์ต๋๋ค.
๋ถํํ๋ IE11 ์ง์์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๋ฒ ์ด์ค์์ ์ฌ์ฉํ ์ ์์ง๋ง ๋ค๋ฅธ ์ฌ๋์ด ์์ ์ ์ฉ๋์ ๋ง๊ฒ ์กฐ์ ํ ์ ์์ต๋๋ค.
์ด๊ฒ์ด ํนํ ๋ง์์ ํผ๋์ค๋ฝ๊ฒ ๋ง๋๋ ๊ฒ์ '๊ธฐ๋ณธ' ๋์์ด ๊ตฌ์ฑ ์์ ํธ๋ฆฌ๋ฅผ ๋ค์ _down_ ๊ฑฐํ์ด ๋ฐ์ํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ค์ ๋๋ฌด๋ฅผ ๊ฐ์ ธ ๊ฐ๋ผ.
<Link>
<Menu (portal)>
<form onSubmit={...}>
<button type="submit">
์ด ์ ํํ ๊ตฌ์ฑ ์์ ์กฐํฉ์ ์ฌ์ฉํ๋ฉด ์ ์ถ ๋ฒํผ์ ํด๋ฆญํ๊ฑฐ๋ ์์ ๋ด๋ถ์ ์
๋ ฅ ํ๋์์ Enter ํค๋ฅผ ๋๋ฅด๋๋ผ๋ ๋ด ์์์ onSubmit
๊ฐ ํธ์ถ๋์ง ์๋ ์ด์ ์ ๋ํด ๋ช ์๊ฐ ๋์ ๊ณ ๋ฏผํ์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก, React Router Link
๊ตฌ์ฑ ์์์ e.preventDefault()
๋ฅผ ์คํํ์ฌ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ค์ ๋ก๋๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ onClick
๊ตฌํ์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ์์์ ์ ์ถํ๊ฒ ๋๋ ์ ์ถ ๋ฒํผ ํด๋ฆญ์ ๊ธฐ๋ณธ ๋์๋ ์ฐจ๋จํ๋ ๋ถํํ ๋ถ์์ฉ์ด ์์ต๋๋ค. ๊ทธ๋์ ์ค๋ ๋ฐฐ์ด ๊ฒ์ ์ ์ถ ๋ฒํผ์ ๋๋ฅด๋ ๊ธฐ๋ณธ ๋์์ผ๋ก onSubmit์ด ์ค์ ๋ก ๋ธ๋ผ์ฐ์ ์ ์ํด ํธ์ถ๋๋ค๋ ๊ฒ์
๋๋ค. Enter๋ฅผ ๋๋ฌ๋ ์ ์ถ ๋ฒํผ์ ํด๋ฆญํ์ฌ ์์ ์ ์ถ์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ์์๊ฐ ์ด๊ฒ์ ์ ๋ง ์ด์ํ๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ ์ ์์ต๋๋ค.
<input>
[ํค ๋๋ฅด๊ธฐ]<button type="submit">
[์๋ฎฌ๋ ์ด์
ํด๋ฆญ]<Menu>
[์ด๋ฒคํธ๊ฐ ํฌํธ ์ธ๋ถ๋ก ์ ํ๋จ]<Link>
[์์ Link
์ ํ๋จ ]<Link>
[ e.preventDefault()
ํธ์ถ ]์ด๊ฒ์ ์ด๋ฏธ DOM์์ ๋ฒํผ๊ณผ ์์์ ์ ๋ฌํ์ง๋ง Link
๋ ์ด๊ฒ๊ณผ ์๋ฌด ๊ด๋ จ์ด ์์ผ๋ฉฐ ์ด ๋์์ ์ ํ ์ฐจ๋จํ ์๋๋ ์์์ต๋๋ค.
๋๋ฅผ ์ํ ์๋ฃจ์
(๋๊ตฐ๊ฐ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ)์ onClick={e => e.stopPropagation()}
๋ก div์ <Menu>
์ฝํ
์ธ ๋ฅผ ๋ํํ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์๋ฃจ์
์ด์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ ์์ ์ ๋ฌธ์ ๋ฅผ ์ถ์ ํ๋ ๋ฐ ๋ง์ ์๊ฐ์ ํ๋นํ๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ ํ๋์ด ์ ๋ง ์ง๊ด์ ์ด์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๋๋ฅผ ์ํ ์๋ฃจ์ (๋๊ตฐ๊ฐ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ)์
onClick={e => e.stopPropagation()}
๋ก div์<Menu>
์ฝํ ์ธ ๋ฅผ ๋ํํ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์๋ฃจ์ ์ด์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ ์์ ์ ๋ฌธ์ ๋ฅผ ์ถ์ ํ๋ ๋ฐ ๋ง์ ์๊ฐ์ ํ๋นํ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ ํ๋์ด ์ ๋ง ์ง๊ด์ ์ด์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ โ ๋ฌธ์ ์ ๊ฐ _๊ฐ๋ณ ์ธ์คํด์ค_์๋ _๋ฒ๊ทธ๋ฅผ ๊ฒฝํํ๊ณ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ณํ๋ฉด_ ๋์ผํ ์ฌ์ด ์๋ฃจ์ ์ด ์์ต๋๋ค. React ํ์ด ์ฌ๊ธฐ์์ ํ๊ณ ๋ ๊ฒ์ ๋งค์ฐ ๊ฐํ๋ฅธ ๋ฒฝ์ผ๋ก ๋ ์คํจ์ ๊ตฌ๋ฉ์ด์ด๋ฉฐ, ๊ทธ๋ค๋ก๋ถํฐ ๊ทธ๊ฒ์ ๋ํ ์น์ธ์ ๋ฃ์ง ๋ชปํ๋ ๊ฒ์ ์ค๋ง์ค๋ฝ์ต๋๋ค.
ํฌํธ์์ mouseenter
์๊ธฐ์น ์๊ฒ ๋ฒ๋ธ๋ง๋๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น
ํ๋ ๋ฐ ๋ฉฐ์น ์ ๋ณด๋์ต๋๋ค. ํฌํธ div์ onMouseEnter={e => e.stopPropagation()}
๊ฐ ์์ด๋ ์ด๋ฒคํธ๋ https://github.com/facebook/react/issues/11387#issuecomment -340009465(์ฒซ ๋ฒ์งธ ์ด ๋ฌธ์ ์ ๋ํ ์๊ฒฌ). mouseenter
/ mouseleave
๋ ์ ์ด์ ๊ฑฐํ์ด ๋์ง ์์์ผ ํฉ๋๋ค...
์๋ง๋ ๋ ์ด์ํ ๊ฒ์
๋๋ค. mouseenter
ํฉ์ฑ ์ด๋ฒคํธ ๋ฒ๋ธ์ด ํฌํธ์์ ๋ฒํผ์ผ๋ก ์ฐ๊ฒฐ๋๋ ๊ฒ์ ๋ณผ ๋ e.nativeEvent.type
๋ mouseout
์
๋๋ค. React๋ ๋ฒ๋ธ๋ง ๋ค์ดํฐ๋ธ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฒ๋ธ๋ง๋์ง ์๋ ํฉ์ฑ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๊ณ ์์ต๋๋ค. stopPropagation
๊ฐ ํฉ์ฑ ์ด๋ฒคํธ์์ ํธ์ถ๋์์์๋ ๋ถ๊ตฌํ๊ณ .
@gaearon @trueadm ์ด ๋ฌธ์ ๋ ํ์ฌ 2๋ ๋์ ์ผ๊ด๋๊ณ ์์ฒญ๋ ์ข์ ์ ์ผ๊ธฐํ์ต๋๋ค. ์ด ์ค๋ ๋๋ React์์ ๊ฐ์ฅ ํ๋ฐํ ์ด์ ์ค ํ๋์ ๋๋ค. ์ ๋ฐ , ํ์์ ๋๊ตฐ๊ฐ๊ฐ ์ฌ๊ธฐ์ ๊ธฐ์ฌํ ์ ์์ต๋๊น?
์ ๊ฒฝ์ฐ์๋ Button์ ํด๋ฆญํ์ฌ Window ๊ตฌ์ฑ ์์๋ฅผ ์ด๋ฉด Window๋ฅผ ํด๋ฆญํ๋ฉด ์ํ ๋ณ๊ฒฝ์ ์ผ์ผํจ ๋ฒํผ์ด ํด๋ฆญ๋๊ธฐ ๋๋ฌธ์ ์ฐฝ์ด ์ฌ๋ผ์ง๋๋ค.
์ ๋ React๋ฅผ ์ฒ์ ์ ํ๊ณ jQuery์ vanillia JS๋ฅผ ์ฃผ๋ก ์ฌ์ฉํ์ง๋ง ์ด๊ฒ์ ๋ง์์ ์ธ๋ฆฌ๋ ๋ฒ๊ทธ์ ๋๋ค. ์ด ๋์์ด ์์๋๋ ๊ฒฝ์ฐ๊ฐ 1% ์ ๋ ์์ ์ ์์ต๋๋ค.
@diegohaz ์ ๋ ๊ฐ์ง ์๋ฃจ์
์ด ๋ง์ ์ ๋ค์ง๋ง ์ฌ์ ํ createPortal
์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ์ค์งํ๋ ์ต์
์ด ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ด ํน์ ์ฌ์ฉ ์ฌ๋ก๋ ๋๊ตฌ ์ค๋ช
์ onMouseLeave
๋ฐ onMouseEnter
ํธ๋ค๋ฌ๊ฐ ํด๋น ํ์ ํฌํธ ํ์ ํญ๋ชฉ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋๋ ๊ฒฝ์ฐ์์ต๋๋ค. ๊ธฐ๋ณธ ์ด๋ฒคํธ๋ ํฌํธ ํ์ ํญ๋ชฉ์ด DOM ํ์ ํญ๋ชฉ์ด ์๋๋ฏ๋ก ๋ฌด์ํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ์์ ํ์ต๋๋ค.
ํฌํธ์์ ๋ฒ๋ธ๋ง์ ์ค์งํ๋ ์ต์ ์ ๊ฒฝ์ฐ +1์ ๋๋ค. ํฌํธ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์์๋๋ ๊ตฌ์ฑ ์์์ ๋ํ ํ์ (์์ ๋์ )๋ก ๋ฐฐ์นํ๋ ๊ฒ์ด ์ ์๋์์ง๋ง ๋ง์ ์ฌ์ฉ ์ฌ๋ก(๋ด ๊ฒฝ์ฐ ํฌํจ)์์๋ ์๋ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ง์นจ๋ด ReactDOM.unstable_renderSubtreeIntoContainer
๊ฐ ์ ๊ฑฐ ๋ ๊ฒ ๊ฐ์ต๋๋ค , ๊ณง ์ด ๋ฌธ์ ์ ๋ํ ํฉ๋ฆฌ์ ์ธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋จ์ง ์์ ๊ฒ์์ ์๋ฏธํฉ๋๋ค...
^ ๋์์ฃผ์ธ์ @trueadm -nobi ๋น์ ์ ์ฐ๋ฆฌ์ ์ ์ผํ ํฌ๋ง์ ๋๋ค
GitHub์์ ping์ ์คํํด๋ ์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค ๐
ํธ์ํฐ ๊ณ์ ์ด ํ์ฑํ๋ ๋๊ตฐ๊ฐ๊ฐ ๊ธฐ์ฌ์ ์ค ํ ๋ช
์ ํ๊ทธํ์ฌ ์ด์ ๋ํด ํธ์ํ ์ ์์๊น์?
์ด ๋ฌธ์ ์ ๋ํด ๋ด +1์ ์ถ๊ฐํฉ๋๋ค. Notion์์๋ ํ์ฌ React.createPortal
์ด์ ์ ์ฌ์ฉ์ ์ ์ ํฌํธ ๊ตฌํ์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ์ปจํ
์คํธ ์ ๊ณต์๋ฅผ ์ ํธ๋ฆฌ์ ์๋์ผ๋ก ์ ๋ฌํฉ๋๋ค. React.createPortal
๋ฅผ ์ฑํํ๋ ค๊ณ ํ์ง๋ง ์๊ธฐ์น ์์ ๋ฒ๋ธ๋ง ๋์์ผ๋ก ์ธํด ์ฐจ๋จ๋์์ต๋๋ค.
<MenuItem>
๊ตฌ์ฑ ์์ ์ธ๋ถ๋ก <Portal>
๋ฅผ ์ด๋ํ์ฌ ํ์ ๊ฐ ๋๋๋ก ํ๋ @sebmarkbage ์ ์ ์์ ๋จ์ผ ์ค์ฒฉ ์์ค์ ๋ํ ๋ฌธ์ ๋ง ํด๊ฒฐํฉ๋๋ค. ํ์ ๋ฉ๋ด๋ฅผ ํฌํธ ์์ํ๋ ์ฌ๋ฌ ์ค์ฒฉ(์:) ๋ฉ๋ด ํญ๋ชฉ์ด ์๋ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋จ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ ์๋์ผ๋ก ์ค๋๋ ๊ฒ์ผ๋ก ํ์๋์์ต๋๋ค. ์ด ๋ฌธ์ ๊ฐ ์ฌ์ ํ ์ํฅ์ ๋ฏธ์น๋ ๊ฒฝ์ฐ ์๊ฒฌ์ ๋จ๊ฒจ์ฃผ์ธ์ (์: "bump"). ๊ณ์ ์ด์ด
์ถฉ๋.
Dan์ ๊ด๋ จ ๋ฌธ์ ์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ๋๊ธ ์ ๋จ๊ฒผ
@mogelbrod ํ์ฌ ์ถ๊ฐํ ๊ฒ์ด ์์ง๋ง ๊ธฐ์กด ๊ตฌ์ฑ ์์๋ฅผ ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ๊ฒฝ์ฐ ์ด์ ๊ฐ์ ๊ฒ( #11387 (comment) )์ด ํฉ๋ฆฌ์ ์ผ๋ก ๋ณด์ ๋๋ค.
๊ฐ์ ๋ฌธ์ ์ ๋ํ Dan์ ํ์ ์กฐ์น :
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ํ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ด๋ฏธ ํด๋น ๋๋ฉ์ธ ์ง์์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ๊ฐ์ฅ ์ข์ ๋ค์ ๋จ๊ณ๋ ์ํ๋ ๋์๊ณผ ๊ณ ๋ คํ ๋์์ ๋ํ RFC๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค. https://github.com/reactjs/rfcs. "์ด๊ฒ์ ๋ฐ๊พธ์"๋ผ๋ RFC๋ ๋์์ด ๋์ง ์์ ๊ฒ์ ๋๋ค. ์ข์ RFC๋ฅผ ์์ฑํ๋ ค๋ฉด ํ์ฌ ๋์์ด ์๋ ์ด์ ์ ๋ํ ์ดํด์ ๋ค๋ฅธ ์ฌ๋์๊ฒ ํ๊ทํ์ง ์๊ณ ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ ๊ณํ์ด ํ์ํฉ๋๋ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌ ํ๊ณ
unstable_renderSubtreeIntoContainer
๋ ์ง์๋์ง ์์ผ๋ฏ๋ก ์ด ๋ ๊ฐ์ง ๋ ผ์๋ฅผ ํ์ด๋ณด๊ฒ ์ต๋๋ค. ์ ์ฒด API๊ฐ ๊ณ ์ ๋์ด ์ ๋ฐ์ดํธ๋์ง ์๊ธฐ ๋๋ฌธ์ Context ์ ํ๋ฅผ ์ถ๊ฐํ์ง ์์ต๋๋ค.
๋ ผ์๋ ํ๋๊ทธ ๋๋ ๋ค๋ฅธ ์๋ฃจ์ ์ ์ถ๊ฐ๋ฅผ ์ ์ํ๊ธฐ ์ํด React RFC๋ฅผ ํ์คํ ๊ฒ์ํด์ผ ํฉ๋๋ค. ์ด์ ์์ฑ์ ํนํ ๊ด์ฌ์ด ์๋ค๊ณ ๋๋ผ๋ ์ฌ๋์ด ์์ต๋๊น(์๋ง๋ @justjake , @craigkovatch ๋๋ @jquense)? ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ด๊ฐ ๋ฌด์์ ์๊ฐํด ๋ผ ์ ์๋์ง ๋ณผ ๊ฒ์ ๋๋ค!
์ด API๋ฅผ ๋ฐ์ ์ํค๋ ๋ฐ๋ ๊ด์ฌ์ด ์์ง๋ง RFC ์ด์์๋ ๊ด์ฌ์ด ์์ต๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์์ ๋์ด ๋ง๊ณ ์น์ธ๋ ๊ฐ๋ฅ์ฑ์ ๊ฑฐ์ ์์ต๋๋ค. ํต์ฌ ํ์ด ๋ก๋๋งต์ ์์ง ์๋ RFC๋ฅผ ์ค์ ๋ก ๊ณ ๋ คํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
@jquense ์ด๊ฒ์ด ์ ํํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์, ์๋ก์ด API๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ํญ์ ๊ต์ฐจ ์์ ์ด๊ณ ๊ณํ๋ ๋ค๋ฅธ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ํฅ์ ๋ฏธ์น๊ธฐ ๋๋ฌธ์ ๋น์ ๊ณผ ์ผ์นํ์ง ์๋ RFC๋ฅผ ๋ณํฉํ ๊ฐ๋ฅ์ฑ์ ๋ฎ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๊ฐ ์ข ์ข ์๋ํ์ง ์๋ ๊ฒ์ ๋ํด ์ธ๊ธํ์ง ์๋ ๊ฒ์ ๊ณต์ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ์ฝ๊ณ , ํนํ ์ํ๊ณ๊ฐ ๋ ์ ๋ฌธ์ ์ธ ์ฃผ์ ์ ์ ๊ทผํ ๋ ์ฝ์ต๋๋ค. ์๋ฅผ ๋ค์ด https://github.com/reactjs/rfcs/pull/38 , https://github.com/ reactjs/rfcs/pull/150 , https://github.com/reactjs/rfcs/pull/118 , https://github.com/reactjs/rfcs/pull/109 , https://github.com/reactjs/ rfcs/pull/32 ๋ ์ฐ๋ฆฌ๊ฐ ๊ทธ๋ค์ ๋ํด ๋ช ์์ ์ผ๋ก ์ธ๊ธํ์ง ์์์ง๋ง ๋ชจ๋ ์ฐ๋ฆฌ์ ์๊ฐ์ ์ํฅ์ ๋ฏธ์ณค์ต๋๋ค.
๋ค์ ๋งํด์, ์ฐ๋ฆฌ๋ ๋ถ๋ถ์ ์ผ๋ก ์ปค๋ฎค๋ํฐ ์ฐ๊ตฌ ๋ฉ์ปค๋์ฆ์ผ๋ก RFC์ ์ ๊ทผํฉ๋๋ค. ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์ฑ๊ฐ์ ์ด์ ์ ๋ํ @mogelbrod (https://github.com/facebook/react/issues/16721#issuecomment-674748100)์ ์ด ์๊ฒฌ์ RFC์์ ๋ณด๊ณ ์ถ์ ๋ฐ๋ก ๊ทธ ์ข ๋ฅ์ ๋๋ค. ๊ธฐ์กด ์๋ฃจ์ ๊ณผ ๊ทธ ๋จ์ ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ๊ตฌ์ฒด์ ์ธ API ์ ์ ์ ์๋ณด๋ค ๋ ๊ฐ์น๊ฐ ์์ ์ ์์ต๋๋ค.
@gaearon ๋ด ์๊ฒฌ์ ํ์ด ์ธ๋ถ ํผ๋๋ฐฑ์ ๋ฃ์ง ์๋๋ค๋ ์ ์์ด ์๋๋๋ค. ์ ํด๋ด๊ฒ ์ต๋๋ค. ๋ด ์๊ฒฌ์ด ์ ํํ๋ค๊ณ ์๊ฐํฉ๋๋ค. RFC ์ ์ฅ์์์ ์คํ๋๋ _process_๋ ๋ค๋ฅธ ์ฌ๋๋ค๋ก๋ถํฐ RFC๋ฅผ ์๋ฝํ์ง ์์ต๋๋ค. ์ด๋ค RFC๊ฐ ๋ณํฉ๋๋์ง ๋ณด๋ฉด ์ ์ ์ผ๋ก ํต์ฌ ํ์ ๋๋ fb ์ง์์ด๋ฉฐ ๋ค๋ฅธ ์ฌ๋์ด ์๋๋๋ค. ๊ทธ๊ฒ์ ๋ง๋๋ ๊ธฐ๋ฅ์ ์ผ๋ฐ์ ์ผ๋ก ์ฝ๊ฐ ๋ค๋ฅด๋ฉฐ RFC ํ๋ก์ธ์ค์ ์ ํ ์ฐธ์ฌํ์ง ์์ต๋๋ค(์: ๋ํ ID).
๋ค๋ฅธ RFC๋ฅผ ์ดํด๋ณด๊ณ ๊ธฐ๋ฅ ์ค๊ณ์ ๊ธฐ์ฌํ๋ค๋ ์์์ ๋ฃ๊ฒ ๋์ด ๋งค์ฐ ๊ธฐ์ฉ๋๋ค. ๊ทธ๋ฌ๋ "์ฐ๋ฆฌ๋ RFC์ ๋ํด ์ธ๊ธํ ์ ์ด ์์ง๋ง ์ธ๋ถ RFC์ ์ํฅ์ ๋ฐ์์ต๋๋ค." ๋์ ํ์ธ์.
๋ค์ ๋งํด์, ์ฐ๋ฆฌ๋ ๋ถ๋ถ์ ์ผ๋ก ์ปค๋ฎค๋ํฐ ์ฐ๊ตฌ ๋ฉ์ปค๋์ฆ์ผ๋ก RFC์ ์ ๊ทผํฉ๋๋ค.
๊ทธ๊ฒ์ ๋งค์ฐ ํฉ๋ฆฌ์ ์ด์ง๋ง RFC repo๊ฐ โโ๋งํ๋ _its_ ์ ๊ทผ ๋ฐฉ์์ด ์๋๋ฉฐ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ผ๋ฐ์ ์ผ๋ก RFC์ ๋ํด ์๊ฐํ๋ ๋ฐฉ์์ด ์๋๋๋ค. RFC ํ๋ก์ธ์ค๋ ์ผ๋ฐ์ ์ผ๋ก ํ๊ณผ ์ปค๋ฎค๋ํฐ ๊ฐ์ ์ฐ๊ฒฐ์ด์ ์ปค๋ฎค๋์ผ์ด์ ์ง์ ์ด๋ฉฐ ๊ธฐ๋ฅ ๊ณ ๋ ค ๋ฐ ํ๋ก์ธ์ค ์ธก๋ฉด์์ ๊ณตํํ ๊ฒฝ์์ ์ฅ์ ๋๋ค.
์ปค๋ฎค๋ํฐ ๊ฑฐ๋ฒ๋์ค์ ๋ํ ๋ ํฐ ์์ ์ ์ ์ณ๋๊ณ . ์ฌ๋๋ค์๊ฒ ์์ธํ ์ ์์ ์์ฑํ๋ ๋ฐ ์๊ฐ์ ํ ์ ํ๊ณ ๋ฐ์ ํ์ ์นจ๋ฌต์ ๋ง๋๋ ๋์ ๋ค๋ฅธ ์ธ๋ถ ์ฐธ๊ฐ์์๊ฒ ์ด๋ฅผ ๋ฐฉ์ดํ๋๋ก ์์ฒญํ๋ ๊ฒ์ ๋๋ดํ๊ณ FB๊ฐ OSS์ ๋ํ ์์ ์ ์๊ตฌ์๋ง ๊ด์ฌ์ ๊ฐ๋๋ค๋ ์ธ์์ ์ ๊ทน์ ์ผ๋ก ๊ฐํํฉ๋๋ค. ๋๋ ๋น์ ์ด ๊ทธ๋ฐ ์์ผ๋ก ๋๋ผ๊ฑฐ๋ ๋์์ธํ์ง ์์ ๊ฒ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์๊ธฐ ๋๋ฌธ์ ๋์๊ฐ๋ฉ๋๋ค.
RFC ํ๋ก์ธ์ค๊ฐ "์ฌ๊ธฐ์ ์ฐ๋ ค ์ฌํญ๊ณผ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ค๋ช ํ ์ ์๋ ๊ณณ์ด ์์ผ๋ฉฐ ์ด ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ ์์ ์ ๋๋ฌํ๋ฉด ์ฝ์ ๊ฒ์ ๋๋ค". ์์งํ ์ข์ ์ ๊ทผ์ ๋๋ค. ์ปค๋ฎค๋ํฐ๊ฐ ์ด๋ฅผ ๋ช ์์ ์ผ๋ก ์ค๋ช ํ๋ฉด ์ด์ต์ ์ป์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ppl์ด ๋ค๋ฅธ RFC ํ๋ก์ธ์ค์ ๋์ผํ ์์ค์ ์ฐธ์ฌ ๋ฐ ์ฐธ์ฌ๋ฅผ ๊ฐ์ ํ ๋ค์ ์ ๋๋ก ์คํ๋์ง ์์ ๋ ์ ๊ทน์ ์ผ๋ก ๋๋ดํ ๊ฒ์ ๋๋ค. ๋ค๋ฅธ ๊ธฐ์ฌ์๋ณด๋ค ์ฝ๊ฐ ๋ ํต์ฐฐ๋ ฅ์ด ์์ด๋ ํ์คํ ๊ทธ๋ฐ ์ธ์์ ๋ฐ์์ต๋๋ค.
๋ฌผ๋ก , ๋๋ ๊ทธ ๋ชจ๋ ๊ฒ์ ๋์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ์ด๊ฒ์ ๋ฉํ ์ฐ๋ ๋๋ก ๋ฐ๊พธ๊ณ ์ถ์ง๋ ์์ง๋ง ์ฌ๋๋ค์ด ์ด ์ฐ๋ ๋์ ๋ํด ๊ณ์ ํ(ping)์ ํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์์ผ๋ก ๋์๊ฐ๊ธฐ ์ํด ํ ์ ์๋ ๊ฐ์ฅ ์คํ ๊ฐ๋ฅํ ์ผ์ ์๋ ๋ฐฉ์์ ๋ํ ์ ์์ ์์ฑํ์ฌ ๋ ๊ฐ์ง ๋ชจ๋์ ๋ํด ์ฐ๋ คํ๋ ๊ฒ์ ๋๋ค. ์ธก๋ฉด์ ๊ณ ๋ คํ๊ณ ๋ฌธ์ ๊ณต๊ฐ์ ๋ํ ๊น์ ์ดํด๋ฅผ ์์งํฉ๋๋ค . ๋๋ ์ด๊ฒ์ด ์ฌ๋๋ค์ด (์ฐ๋ฆฌ๊ฐ RFC์ ์ด๋ป๊ฒ ๋ฐ์ํ๋์ง์ ๊ธฐ์ดํ์ฌ) ์ฌ๋๋ค์ด ํ๊ณ ์ถ์ด ํ๋ ๊ฒ์ด ์๋๋ผ๋ฉด ์์ ํ ์ดํดํฉ๋๋ค. ์ด๊ฒ์ด ์ ๊ฐ ๋ ์ผ์ฐ ์ ์ํ์ง ์์ ์ด์ ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ์ธ์ ์ธ ํ์ ๊ณ์ ๋ฐ๊ธฐ ๋๋ฌธ์ ์ ์ํ๊ณ ์ถ์ต๋๋ค. ๋๊ธฐ๊ฐ ๋ถ์ฌ๋ ์ฌ๋์ ์ํ ์ต์ ์ผ๋ก.
์ถฉ๋ถํ ๊ณตํํฉ๋๋ค. ์ด๊ฒ์ RFC์ ๋ํ ๋ฉํ๋ฅผ ์ป๊ธฐ์ ์ ํฉํ ์ฅ์๊ฐ ์๋๋๋ค. :)
@gaearon ์ด๊ฒ์ ํ์ฌ React์์ ์ด๋ฆฐ 6๋ฒ์งธ๋ก ๊ฐ์ฅ ๋ง์ด
์ด ๋ฌธ์ ์ ๋ํด ์ธ๊ธํ ๊ฒ์ ์ ๊ฐ์ค๋ฝ๊ฒ ์๊ฐํ๋ฉฐ ์ปค๋ฎค๋ํฐ RFC์ ๋ํ ์ ์์ ์ฒ ํํฉ๋๋ค. ์๋ง๋ ๋์ ์๊ฐ์ผ ๊ฒ์ ๋๋ค. ๋๋ ์ด ๋ฌธ์ ๊ฐ ๋งค์ฐ ๊ฐ์ ์ ์ด๋ฉฐ ์ธ๊ฐ์ผ๋ก์ ๊ฐ์ธ์ ์ผ๋ก ๊ทธ๊ฒ์ ๊ด์ฌํ๋ ๊ฒ์ด ์ด๋ ต๋ค๋ ๊ฒ์ ์๊ฒ ๋์๋ค๊ณ ๋ง๋ถ์ด๊ณ ์ถ์ต๋๋ค. ๋น๋ก ๊ทธ๊ฒ์ด ์ค์ํ๊ณ ๋ง์ ์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ๋ํด ๊ฐํ๊ฒ ๋๋๋ค๋ ๊ฒ์ ์ดํดํ์ง๋ง ๋ง์ ๋๋ค.
์ด ์ค๋ ๋์ ์ํ์ ๋ํด ๊ฐ๋จํ ๋ต๋ณํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋จผ์ , ์ด ์ค๋ ๋์์ ํ์ ์กฐ์น๋ฅผ ๊ณ์ํ์ง ์๋ ๊ฒ์ ๋ํด ๋๊ธ์ ๋ฌ๊ณ ์์ํด ํ์ จ๋ ๋ถ๋ค๊ป ์ฃ์กํ๋ค๋ ๋ง์์ ๋๋ฆฌ๊ณ ์ถ์ต๋๋ค. ๋ด๊ฐ ์ธ๋ถ์์ ์ด ๋ฌธ์ ๋ฅผ ์ฝ์๋ค๋ฉด React ํ์ด ์ค์๋ฅผ ์ ์ง๋ ๊ณ , ์ธ์ ํ๋ ค ํ์ง ์์์ผ๋ฉฐ, ๊ฐ๋จํ ํด๊ฒฐ์ฑ ์ ๊ธฐ๊บผ์ด ์์ ์ํฅ์ด ์๋ค๋ ์ธ์์ ๋ฐ์์ ๊ฒ์ ๋๋ค. ๋ ๊ฑฐ์ผ!") 2๋ ๋๊ฒ ์ปค๋ฎค๋ํฐ๋ฅผ ๋๋ณด์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๋ ๋น์ ์ด ์ด๋ป๊ฒ ์ด๋ฐ ๊ฒฐ๋ก ์ ๋๋ฌํ ์ ์๋์ง ์ถฉ๋ถํ ์ดํดํ ์ ์์ต๋๋ค.
๋๋ ์ด ๋ฌธ์ ๊ฐ ๋์ ์ง์ง๋ฅผ ๋ฐ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ์ด ์ค๋ ๋์์ ์ฌ๋ฌ ๋ฒ ์ ๊ธฐ๋์์ต๋๋ค. React ํ์ด ์ด๊ฒ์ด ํฐ ๋ฌธ์ ๋ผ๋ ๊ฒ์ ์์๋ค๋ฉด ๋ ๋นจ๋ฆฌ ํด๊ฒฐํ์ ๊ฒ์ด๋ผ๋ ๊ด์ ์์ ๋ณผ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ ๋ ์ด๊ฒ์ด ๊ณจ์นซ๊ฑฐ๋ฆฌ
์ด ๋ฌธ์ ์๋ ๊ธด๊ธํ ์ฒ๋ฆฌํด์ผ ํ๋ ๋ณด์ ์ทจ์ฝ์ ์ด๋ ์ถฉ๋๊ณผ ๋ฌ๋ฆฌ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ wokaround๊ฐ ์๋ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค(๊ทธ๋ฌ๋ ์ด์์ ์ด์ง๋ ์๊ณ ์ฑ๊ฐ์ค ์ ์์). ๊ทธ ์ค ์ผ๋ถ๋ ํนํ React 16 ์ด์ ์ ์์ฑ๋ ์ฝ๋ ์ฃผ๋ณ์์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด ๋ฌธ์ ๊ฐ ์์ฌํ ์ฌ์ง ์์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ์ค๋ง์ค๋ฌ์ ์ง๋ง ๋์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ง์ ์ฌ๋๋ค์ด ์์ง๋ง ๊ตฌ์ฒด์ ์ธ ์๊ฐ ๋ด์ ๋์ํด์ผ ํ๋ ์ถฉ๋์ด๋ ๋ณด์ ๋ฌธ์ ์๋ ์ฌ์ ํ ๋ค๋ฅธ ์ข ๋ฅ์ ๋ฌธ์ ์ ๋๋ค.
๋ํ ๋ด์ผ ๊ตฌํํ ์ ์๋ ๊ฐ๋จํ ์๋ฃจ์ ์ด ์๋ค๋ ํ์ ๋์ํ์ง ์์ต๋๋ค. ๋น๋ก ์ฐ๋ฆฌ๊ฐ ์ด๊ธฐ ํ๋์ ์ค์๋ผ๊ณ ์๊ฐ ๋ ๋๋ค๋ ๊ฒ์ ์๋ฏธ ํฉ๋๋ค. ์ผ๋ถ ์ฌ๋ก๋ ์์ ํ์ง๋ง ๋ค๋ฅธ ์ฌ๋ก๋ ์ค๋จํ๋ฉด ์๋ฌด๋ฐ ์ง์ ์ด ์์๊ณ ์์ฒญ๋ ํผ๋์ ์ผ์ผ์ผฐ์ต๋๋ค. ์ด ๋ฌธ์ ์์ ํ์ฌ ๋์์ด ์ ์๋ํ๋ ๊ฒฝ์ฐ์ ๋ํด์๋ ๋ฃ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๊นจ๊ณ ๋์์ผ ๊ทธ๊ฒ์ ๋ํด ๋ฃ๊ฒ ๋ ๊ฒ์ ๋๋ค.
์๋ฅผ ๋ค์ด, ํ์ฌ ๋์์ ์ฐ๋ฆฌ๊ฐ ๊ฝค ์ค๋ซ๋์ ์ฐ๊ตฌํด ์จ ์ ์ธ์ ํฌ์ปค์ค ๊ด๋ฆฌ ์ฌ์ฉ ์ฌ๋ก์ ์ค์ ๋ก ์ ๋ง ๋์์ด ๋ฉ๋๋ค. ํฌํธ์์๋ ๋ถ๊ตฌํ๊ณ ๋ถํ ํธ๋ฆฌ์ ๊ด๋ จํ์ฌ ๋ชจ๋ฌ "๋ด๋ถ"์์ ๋ฐ์ํ๋ ํฌ์ปค์ค/๋ธ๋ฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ์ด ์ค๋ ๋์์ ์ ์๋ "๋จ์ํ" createPortal(tree, boolean)
์ ์์ ์ ๊ณตํ๋ ๊ฒฝ์ฐ ํฌํธ ์์ฒด์์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋์์ ๋ํด "์ ์" ์๊ธฐ ๋๋ฌธ์ ์ด ์ฌ์ฉ ์ฌ๋ก๋ ์๋ํ์ง ์์ต๋๋ค. ๊ฐ๋ฅํ ์๋ฃจ์
์ ํ์ํ๋ ค๋ฉด ์์ญ ๊ฐ์ง ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ฉฐ ๊ทธ ์ค ์ผ๋ถ๋ ์์ง ์์ ํ ์ดํด๋์ง๋ ์์์ต๋๋ค. ์ด๊ฒ์ ์ด๋ ์์ ์์ ๋ฐ๋์ ํด์ผ ํ๋ ์ผ์ด์ง๋ง ์ฌ๋ฐ๋ฅด๊ฒ ํ๊ธฐ ์ํด์๋ ์์ฒญ๋ ์๊ฐ์ด ์์๋๋ฉฐ ์ง๊ธ๊น์ง ์ง์คํ ์ ์์์ต๋๋ค.
ํนํ ์ด๋ฒคํธ๋ ๊น๋ค๋ก์ด ์์ญ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ๋ ๋ช ๋ ๋์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง์ ๋ณ๊ฒฝ์ ๊ฐํ์ผ๋ฉฐ ์ฌํด๋ ์ด๊ฒ์ด ํฐ ์ด์ ์ด์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ํ ๋ฒ์ ๋๋ฌด ๋ง์ ์ผ์ ํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๋ ํ์ผ๋ก์ ๋ง์ ๋ฌธ์ ์ ์๊ฒ ์ง์คํ๊ธฐ๋ณด๋ค ๋ช ๊ฐ์ง ๋ฌธ์ ์ ๊น์ด ์ง์คํ๋ ค๊ณ ๋ ธ๋ ฅํฉ๋๋ค. ๋ถํํ๋ ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๋ค๋ฅธ ์ค์ํ ๊ฒฉ์ฐจ๋ฅผ ์์ ํ๋ ์ค์ด๊ฑฐ๋ ๋ฌธ์ ๋ฅผ ์์ํ ํด๊ฒฐํ ๋์ ์ค๊ณ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ถ ๊ฐ๋ ์ ๊ฒฐํจ๊ณผ ๊ฒฉ์ฐจ๊ฐ ๋ช ๋ ๋์ ์ฑ์์ง์ง ์์ ์ ์์์ ์๋ฏธํฉ๋๋ค. ๋๋ ์ด๊ฒ์ด ๋ฃ๊ณ ์ค๋ง ์ค๋ฝ๋ค๋ ๊ฒ์ ์๊ณ ์์ผ๋ฉฐ ์ด๊ฒ์ด ๋ด๊ฐ ์ด ์ค๋ ๋์์ ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์์๋ ์ด์ ์ ์ผ๋ถ์ ๋๋ค. ๋ค๋ฅธ ์ ์ฌํ ์ค๋ ๋๊ฐ ๋ฌธ์ ์ ๊ฐ๋ฅํ ์๋ฃจ์ ์ ๋ํ ๋ ๊น์ ์ค๋ช ์ผ๋ก ๋ฐ๋์๊ณ ๋์์ด ๋์์ง๋ง ์ด ์ค๋ ๋๋ ๋๋ถ๋ถ "+1"์ ํ์์ "๋จ์ํ" ์์ ์ ๋ํ ์ ์์ผ๋ก ๋ฐ๋์๊ณ ์ด๊ฒ์ด ์ด๋ ค์ด ์ด์ ์ ๋๋ค. ์๋ฏธ์๊ฒ ์ฐธ์ฌํฉ๋๋ค.
์ด๊ฒ์ด ์ฌ๋๋ค์ด ๋ฃ๊ณ ์ถ์ดํ๋ ๋๋ต์ด ์๋๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง, ์๋ฌด ๋๋ต๋ ํ์ง ์๋ ๊ฒ๋ณด๋ค๋ ๋์์ผ๋ฉด ํฉ๋๋ค.
์ธ๊ธํ ๊ฐ์น๊ฐ ์๋ ๋ ๋ค๋ฅธ ์ฌํญ์ ์ด ์ค๋ ๋์ ์ค๋ช ๋ ์ผ๋ถ ๋ฌธ์ ์ ์ด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐ๋์์ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด:
ํนํ: ํฉ์ฑ ํฌ์ปค์ค ์ด๋ฒคํธ์์ stopPropagation์ ํธ์ถํ์ฌ ํฌํธ ๋ฐ์ผ๋ก ๋ฒ๋ธ๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ฉด stopPropagation์ด #document์ ์๋ React์ ์บก์ฒ๋ ํธ๋ค๋ฌ์ ์๋ ๋ค์ดํฐ๋ธ ํฌ์ปค์ค ์ด๋ฒคํธ์์๋ ํธ์ถ๋ฉ๋๋ค.
React๋ ๋ ์ด์ ๋ฒ๋ธ๋ง์ ์๋ฎฌ๋ ์ดํธํ๊ธฐ ์ํด ์บก์ฒ ๋จ๊ณ๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉฐ ๋ ์ด์ ๋ฌธ์์ ์ด๋ฒคํธ๋ฅผ ์์ ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ์ข์ ๊ฐ์ ๋ฌด์ํ์ง ์๊ณ ๋ค๋ฅธ ๋ณ๊ฒฝ ์ฌํญ์ ๋น์ถ์ด ์ง๊ธ๊น์ง ๊ฒ์ ๋ ๋ชจ๋ ๊ฒ์ ์ฌํ๊ฐํด์ผํฉ๋๋ค.
๊ธฐ๋ณธ ์ด๋ฒคํธ๋ ์ฌ์ ํ ๊ฑฐํ์ด ์ผ๊ณ React ์ฝ๋๋ ๋๋ถ๋ถ jQuery ์ ํ๋ฆฌ์ผ์ด์ ๋ด๋ถ์์ ํธ์คํ ๋๊ธฐ ๋๋ฌธ์ ์ ์ญ jQuery keyDown ํธ๋ค๋ฌ๋
์ฌ์ ํ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ต๋๋ค.
์ ์ฌํ๊ฒ, React 17์ ๋ฃจํธ์ ํฌํธ ์ปจํ ์ด๋์ ์ด๋ฒคํธ๋ฅผ ์ฒจ๋ถํ ๊ฒ์ด๋ฏ๋ก(์ค์ ๋ก ๊ทธ ์์ ์์ ๊ธฐ๋ณธ ์ ํ๋ฅผ ์ค์ง) ์ ๋ ํด๊ฒฐ๋ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค.
renderSubtreeIntoContainer
์ ๋ํ ํฌ์ธํธ๊ฐ ์ ๊ฑฐ๋ฉ๋๋ค. ๋ง ๊ทธ๋๋ก ReactDOM.render
๊ณผ์ ์ ์ผํ ์ฐจ์ด์ ์ Legacy Context๋ฅผ ์ ํํ๋ค๋ ๊ฒ์
๋๋ค. renderSubtreeIntoContainer
ํฌํจํ์ง ์๋ ๋ฆด๋ฆฌ์ค๋ Legacy Context๋ ํฌํจํ์ง ์์ผ๋ฏ๋ก ReactDOM.render
๋ 100% ๋์ผํ ๋์์ผ๋ก ๋จ์ ๊ฒ์
๋๋ค. ๋ฌผ๋ก ์ด๊ฒ์ ๋ ๊ด๋ฒ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ์ง๋ง ํนํ renderSubtree
๋ํ ์ฐ๋ ค๋ ๋ค์ ์๋ชป๋ ์์น์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@gaearon
renderSubtreeIntoContainer
์ ๋ํ ํฌ์ธํธ๊ฐ ์ ๊ฑฐ๋ฉ๋๋ค. ๋ง ๊ทธ๋๋กReactDOM.render
๊ณผ์ ์ ์ผํ ์ฐจ์ด์ ์ Legacy Context๋ฅผ ์ ํํ๋ค๋ ๊ฒ์ ๋๋ค.renderSubtreeIntoContainer
ํฌํจํ์ง ์๋ ๋ฆด๋ฆฌ์ค๋ Legacy Context๋ ํฌํจํ์ง ์์ผ๋ฏ๋กReactDOM.render
๋ 100% ๋์ผํ ๋์์ผ๋ก ๋จ์ ๊ฒ์ ๋๋ค. ๋ฌผ๋ก ์ด๊ฒ์ ๋ ๊ด๋ฒ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ์ง๋ง ํนํrenderSubtree
๋ํ ์ฐ๋ ค๋ ๋ค์ ์๋ชป๋ ์์น์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ด์ ์ธ๊ธํ์ จ์ผ๋ ์๋ ์ฝ๋๊ฐ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ์์ด React Portal์ ๋ํด ์ ํจํ๊ณ ์์ ํ ๊ตฌํ์ด ๋ ์ ์์์ง ๊ถ๊ธํฉ๋๋ค.
function Portal({ children }) {
const containerRef = React.useRef();
React.useEffect(() => {
const container = document.createElement("div");
containerRef.current = container;
document.body.appendChild(container);
return () => {
ReactDOM.unmountComponentAtNode(container);
document.body.removeChild(container);
};
}, []);
React.useEffect(() => {
ReactDOM.render(children, containerRef.current);
}, [children]);
return null;
}
์ผ๋ถ ํ ์คํธ๊ฐ ํฌํจ๋ CodeSandbox: https://codesandbox.io/s/react-portal-with-reactdom-render-m22dj?file=/src/App.js
Modern Context๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ์ฌ์ ํ ์์ง๋ง ์ด๊ฒ์ ์๋ก์ด ๋ฌธ์ ๊ฐ ์๋๋๋ค( renderSubtree
๋ ์ํฅ์ ๋ฐ์ต๋๋ค). ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ์ปจํ
์คํธ ๊ณต๊ธ์๋ก ํธ๋ฆฌ๋ฅผ ๋๋ฌ์ธ๋ ๊ฒ์
๋๋ค. ์ ๋ฐ์ ์ผ๋ก ํธ๋ฆฌ๋ฅผ ์ค์ฒฉํ๋ ๊ฒ์ ์ด์์ ์ด์ง ์์ผ๋ฏ๋ก ๊ธฐ์กด ๊ธฐ์กด ์ฝ๋ ์๋๋ฆฌ์ค ์ด์ธ์ ๋ค๋ฅธ ํจํด์์๋ ์ด ํจํด์ผ๋ก ์ ํํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค.
๋ค์ ํ๋ฒ @gaearon์ ์จ์ฃผ์ ์ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค!
๊ณ ์ฅ๋ ์ผ์ด์ค + ํด๊ฒฐ ๋ฐฉ๋ฒ(React v17์ฉ์ผ๋ก ์ ๋ฐ์ดํธ๋จ) ๋ชฉ๋ก์ ์ง๊ณํ๋ ๊ฒ์ด ํต์ฌ ํ ์ธ๋ถ์ ๋๊ตฐ๊ฐ์๊ฒ ๊ฐ์ฅ ์์ฐ์ ์ธ ์ผ์ธ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค(ํ๋ฆฐ ๊ฒฝ์ฐ ์์ ํด ์ฃผ์ธ์!).
๋๋ ์์ผ๋ก ๋ช ์ฃผ ๋์ ๋ช์ ๋น ์ก์ง๋ง ์ต๋ํ ๋นจ๋ฆฌ ํ๋ ๊ฒ์ ๋ชฉํ๋ก ์ผ๊ณ ์์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋์ด ๋ ์ผ์ฐ ์ด ์์ ์ ์ํํ ์ ์๊ฑฐ๋ ์ค๋ํซ( @diegohaz๊ฐ ๋ฐฉ๊ธ ํ ๊ฒ์ฒ๋ผ)์ผ๋ก ์ฐจ์ํ ์ ์๋ค๋ฉด ๊ทธ๊ฒ์ ๊ต์ฅํ ๊ฒ์ ๋๋ค!
์ฌ๋ก ๋ชฉ๋ก์ ์ง๊ณํ๋ ๊ฒ์ ํ์คํ ์ ์ฉํ ๊ฒ์ด์ง๋ง, ๊นจ์ง ์ฌ๋ก๋ฟ๋ง ์๋๋ผ ํ์ฌ ํ๋์ด ์๋ฏธ๊ฐ ์๋ ์ฌ๋ก๋ ํฌํจํด์ผ ํ๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค.
์ถ๊ฐํ ๊ณต๊ฐ ๊ณต๊ฐ์ด ์๋ค๋ฉด ์ ํฌ ์ฑ๊ณผ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์ ๋ชจ๋์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ธฐ๊บผ์ด ์ถ๊ฐํ๊ฒ ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋๋ ๋๋๋ก ์ฑ๊ฐ์์ง๋ง ํด๊ฒฐํ๊ธฐ ์ฝ๋ค๋ Dan์ ๋ง์ ๋์ํฉ๋๋ค. React์ ๋ฒ๋ธ๋ง์ ์ํ๋ ๊ฒฝ์ฐ React์ ๋์ ์์ด ์ผ์ด์ค๋ฅผ ๋ฎ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.
์ฌ๋ก ๋ชฉ๋ก์ ์ง๊ณํ๋ ๊ฒ์ ํ์คํ ์ ์ฉํ ๊ฒ์ด์ง๋ง, ๊นจ์ง ์ฌ๋ก๋ฟ๋ง ์๋๋ผ ํ์ฌ ํ๋์ด ์๋ฏธ๊ฐ ์๋ ์ฌ๋ก๋ ํฌํจํด์ผ ํ๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค.
๋๊ตฐ๊ฐ ์ ์๊ฒ ์์กดํ๋ ์คํ ์์ค ์ฝ๋/์ถ์ถ๋ ์ฝ๋๋ฅผ ์๋ ค์ค ์ ์๋ค๋ฉด ์ด๊ฒ๋ค์ ํฌํจํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค! ์ด์ ์ ์ธ๊ธํ๋ฏ์ด ํ์ฌ ํ๋์ ๋ฌธ์ ๊ฐ ์๋ ์ฌ๋๋ค๋ง ์ด ๋ฌธ์ ์ ๊ด๋ จ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ฐพ๊ธฐ๊ฐ ์ฝ๊ฐ ์ด๋ ต์ต๋๋ค ๐
์ถ๊ฐํ ๊ณต๊ฐ ๊ณต๊ฐ์ด ์๋ค๋ฉด ์ ํฌ ์ฑ๊ณผ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์ ๋ชจ๋์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ธฐ๊บผ์ด ์ถ๊ฐํ๊ฒ ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋๋ ๋๋๋ก ์ฑ๊ฐ์์ง๋ง ํด๊ฒฐํ๊ธฐ ์ฝ๋ค๋ Dan์ ๋ง์ ๋์ํฉ๋๋ค. React์ ๋ฒ๋ธ๋ง์ ์ํ๋ ๊ฒฝ์ฐ React์ ๋์ ์์ด ์ผ์ด์ค๋ฅผ ๋ฎ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.
์ผ๋์ ๋๊ณ ์๋ ํน์ ๊ณต๊ฐ์ด ์๊ฑฐ๋ ์ฌ๋ก๋น ํ๋์ ์ฝ๋์๋๋ฐ์ค (๋๋ jsfiddle ๋ฑ)๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ด ์คํํฐ๋ก ์๋ํฉ๋๊น? ๋ช ๊ฐ์ง ์ฌ๋ก๋ฅผ ์์งํ๋ฉด ๋ชจ๋ ์ปดํ์ผ์ ์๋ํ ์ ์์ต๋๋ค.
https://github.com/facebook/react/issues/19637 ์์ ์ค๋ ๋๋ฅผ ์์ํ์ต๋๋ค
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ทธ๋ง์ ๋ ๋์๊ฒ๋ ๋ถํ์ํ๊ฒ ๋ณต์กํด ๋ณด์ธ๋ค. ๋ฒ๋ธ๋ง ๋์์ ์ฐจ๋จํ ์ ์๋๋ก createPortal์ ์ ํ์ ๋ถ์ธ ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?