๊ธฐ๋ฅ ์์ฒญ์ด ๋ฌธ์ ์ ๊ด๋ จ๋์ด ์์ต๋๊น?
React๋ ๋จ์ผ HTML ๋ฌธ์ ๋ด์์ ๋๋๊ทธ ์ค ๋๋กญ์ ์ ํํฉ๋๋ค. ์ด๋ป๊ฒ๋ ์ธ๋ถ์์ iframe ๋ด๋ถ๋ก ๋๋๊ทธํด์ผ ํฉ๋๋ค.
์ํ๋ ์๋ฃจ์
์ค๋ช
dnd HTML5backend๊ฐ ์ฐฝ์์ ๋๋๊ทธ ์ฝ๋ฐฑ์ ํธ๋ฆฌ๊ฑฐํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ๋ฐ๋ผ์ iframe ๋ด๋ถ์ ๊ตฌ์ฑ ์์๊ฐ ํด๋น ์ฝ๋ฐฑ์ ํธ๋ฆฌ๊ฑฐํ๋๋ก ํ ์ ์๋ค๋ฉด React.createPortal
iframe ๋ด๋ถ์ ๊ตฌ์ฑ ์์๊ฐ ์ธ๋ถ์ ๋์ผํ DndProvider๋ฅผ ๊ฐ๋๋ก ํฉ๋๋ค. ์ด ์ข๊ฒ๋ ์๋ํฉ๋๋ค. ํ์ง๋ง ๋ด๊ฐ ๋์น์ฑ์ง ๋ชปํ ๋ฌธ์ ๊ฐ ์๊ธธ๊น๋ด ๊ฑฑ์ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ HTML5Backend์์๋ ์ฝ๋๊ฐ ๊ทธ๋ ๊ฒ ํธ๋ฆฌํ์ง ์์ต๋๋ค.
import React, {
useRef,
useEffect,
useContext,
forwardRef,
} from 'react';
import classnames from 'classnames';
import { DndContext } from 'react-dnd';
// Frame base on createPortal inside iframe dom.
import Frame from 'react-frame-component';
const events = [
['dragstart', 'handleTopDragStart', false],
['dragstart', 'handleTopDragStartCapture', true],
['dragend', 'handleTopDragEndCapture', true],
['dragenter', 'handleTopDragEnter', false],
['dragenter', 'handleTopDragEnterCapture', true],
['dragleave', 'handleTopDragLeaveCapture', true],
['dragover', 'handleTopDragOver', false],
['dragover', 'handleTopDragOverCapture', true],
['drop', 'handleTopDrop', false],
['drop', 'handleTopDropCapture', true],
];
export const DndFrame = forwardRef((props = {}, ref) => {
const container = useRef(null);
const dndValue = useContext(DndContext) || {};
const { dragDropManager: { backend = {} } = {} } = dndValue;
const { children, className, containerProps = {}, ...others } = props;
const cls = classnames({
'dnd-frame': true,
[className]: !!className,
});
useEffect(() => {
const { current } = container;
if (!current) {
return;
}
// this make callback run in outside window
events.forEach((eventArgs = []) => {
const [name, callbackName, capture = false] = eventArgs;
const callback = backend[callbackName] && backend[callbackName].bind(backend);
current.addEventListener(name, (...args) => {
callback && callback(...args);
}, capture);
});
}, [container.current]);
return (
<Frame className={cls} ref={ref} {...others}>
<div className="dnd-frame-container" ref={container} {...containerProps}>
{ children }
</div>
</Frame>
);
});
๊ณ ๋ คํ ๋์์ ๊ธฐ์ ํ์ญ์์ค.
HTML5Backend๋ก ์ผ๋ถ ์ต์
์ ๋ด๋ณด๋ผ ์ ์์ต๋๋ค.
์ด ์ฝ๋๋ฅผ ๋จ์ํํ๋ ๋ ์ฌ์ด ์๋ฃจ์ ์ ์ฐพ์์ง๋ง ์ด๊ฒ์ด ๋ ๋์ ์๋ฃจ์ ์ธ์ง ํ์ ํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
import React, { useContext, useEffect } from 'react';
import DndProvider, { DndContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Frame, { FrameContext } from 'react-frame-component';
const DndFrame = ({ children }) => {
const { dragDropManager } = useContext(DndContext);
const { window } = useContext(FrameContext);
useEffect(() => {
dragDropManager.getBackend().addEventListeners(window);
});
return children;
};
const Example = () => (
<DndProvider backend={HTML5Backend}>
<Frame>
<DndFrame>
<div>...</div>
</DndFrame>
</Frame>
</DndProvider>
);
@HsuTing ๋ ์ฝ๊ณ ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ ํ HTML5Backend ์ธํฐํ์ด์ค์ ๋ฐ์ธ๋ฉ๋์ด ์์ต๋๋ค. HTML5Backend๊ฐ addEventListeners => addListeners๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์น์ด ๊ณ ์ฅ๋ ๊ฒ์ ๋๋ค.
์ ๋ง ๋ฉ์ง ์์ด๋์ด์ ๋๋ค. ํ์ดํน์์ ๋์์ฌ ๋ ๊ฐ์ง๊ณ ๋๊ฒ ์ต๋๋ค.
2019๋ 8์ 6์ผ ํ์์ผ ์คํ 11:43 ๆ็ฝ[email protected] ์์ฑ:
@HsuTing https://github.com/HsuTing ๋ ์ฝ๊ณ ์ข์ต๋๋ค. ํ์ง๋ง ์ฌ์ ํ
HTML5Backend ์ธํฐํ์ด์ค์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค. HTML5Backend๊ฐ addEventListeners๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒฝ์ฐ
=> addListeners, ์ฐ๋ฆฌ์ ์น์ ๊ณ ์ฅ๋ ๊ฒ์ ๋๋คโ
๋น์ ์ด ํ ๋น๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธํ์ธ์.
https://github.com/react-dnd/react-dnd/issues/1496?email_source=notifications&email_token=AAA3XCDZJS3V5E7YISDRUC3QDJVJLA5CNFSM4IIMWOQ2YY3PNVWWK3TUL52HS4DFVEXG43VMVB
๋๋ ์ค๋ ๋๋ฅผ ์์๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AAA3XCGHNHO3M3CSL5VRUQTQDJVJLANCNFSM4IIMWOQQ
.
์ด ์ฝ๋๋ฅผ ๋จ์ํํ๋ ๋ ์ฌ์ด ์๋ฃจ์ ์ ์ฐพ์์ง๋ง ์ด๊ฒ์ด ๋ ๋์ ์๋ฃจ์ ์ธ์ง ํ์ ํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
import React, { useContext, useEffect } from 'react'; import DndProvider, { DndContext } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import Frame, { FrameContext } from 'react-frame-component'; const DndFrame = ({ children }) => { const { dragDropManager } = useContext(DndContext); const { window } = useContext(FrameContext); useEffect(() => { dragDropManager.getBackend().addEventListeners(window); }); return children; }; const Example = () => ( <DndProvider backend={HTML5Backend}> <Frame> <DndFrame> <div>...</div> </DndFrame> </Frame> </DndProvider> );
๊ทธ๊ฒ์ ํ๋ฅญํ ์ ๊ทผ ๋ฐฉ์์ด๋ฉฐ ์ ์๊ฒ ํจ๊ณผ์ ์ ๋๋ค.
์ด ์ฝ๋๋ฅผ ๋จ์ํํ๋ ๋ ์ฌ์ด ์๋ฃจ์ ์ ์ฐพ์์ง๋ง ์ด๊ฒ์ด ๋ ๋์ ์๋ฃจ์ ์ธ์ง ํ์ ํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
import React, { useContext, useEffect } from 'react'; import DndProvider, { DndContext } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import Frame, { FrameContext } from 'react-frame-component'; const DndFrame = ({ children }) => { const { dragDropManager } = useContext(DndContext); const { window } = useContext(FrameContext); useEffect(() => { dragDropManager.getBackend().addEventListeners(window); }); return children; }; const Example = () => ( <DndProvider backend={HTML5Backend}> <Frame> <DndFrame> <div>...</div> </DndFrame> </Frame> </DndProvider> );
typescript๋ก ์๋ํ ๋ Property 'addEventListeners' does not exist on type 'Backend'
์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
TS์์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
addEventListeners๋ ๋ฐฑ์๋ ์ธํฐํ์ด์ค์ ๋ ธ์ถ๋์ง ์์ต๋๋ค. DOM/๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ธ์ถํ๊ณ ์ถ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ํด์ผ ํ ์ผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
// detect if SSR mode
const DEFAULT_GLOBAL_CONTEXT = typeof window !== 'undefined' ? window : global
const DndFrame = ({ children, globalContext = DEFAULT_GLOBAL_CONTEXT}) => {
const { dragDropManager } = useContext(DndContext);
const { window } = useContext(FrameContext);
const backend = useMemo(() => dragDropManager.getBackend(), [dragDropManager])
useEffect(() => {
// This will required adding an initialize() method to the Backend interface.
// Backend constructors will have to thunk over to it. It could replace constructors, but that would be semver major.
backend.initialize(dragDropManager, globalContext)
backend.setup()
}, [globalContext]);
return children;
};
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ด ์ฝ๋๋ฅผ ๋จ์ํํ๋ ๋ ์ฌ์ด ์๋ฃจ์ ์ ์ฐพ์์ง๋ง ์ด๊ฒ์ด ๋ ๋์ ์๋ฃจ์ ์ธ์ง ํ์ ํ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.