부모 컴포넌트의 DOM 계층 구조 바깥에 있는 (render 영역 밖에 있는) DOM 노드로 자식을 렌더링하는 기능
// indexl.html의 <body>
<div id="root"></div>
<div id="modal"></div>
// index.css
#modal {
position: absolute;
top: 0;
left: 0;
}
// ./src/components/Modal.jsx
import ReactDOM from 'react-dom';
const Modal = ({children}) =>
// children을 modal DOM의 후손 요소로 삽입
ReactDOM.createPortal(children, document.querySelector("#modal"));
export default Modal;
// App.js
function App() {
const [visible, setVisible] = useState(false);
const open = () => {
setVisible(true);
}
const close = () => {
setVisible(false);
}
return <div>
<button onClick={open}>open</button>
{visible && (
<Modal>
<div
style={{
width: '100vw',
height: '100vh',
background: "rgba(0, 0, 0, 0.5)",
}}
onClick={close}
>
Hello
</div>
</Modal>
)}
</div>
}
이 때, Modal은 createPortal을 사용해 id가 modal인 엘리먼트에 render되도록 설정된 상태
👩🏻 따라서 컴포넌트를 특정한 다른 div 안에 넣고싶다면 root 벗어난 곳에서 처리할 수 있도록 createPortal 사용해볼 것! (특히 모달 팝업이나 알림창 구현 시 유용)
하위 컴포넌트의 ref를 상위 컴포넌트에서 사용하게 해주는 기능
이 때 forwardRef()
의 첫번째 매개변수는 props, 두번째 매개변수는 ref
// ./src/components/MyInput.jsx
import React from "react";
import { forwardRef } from "react";
export default forwardRef(function MyInput(props, ref) {
return (
<div>
<p>MyInput</p>
<input ref={ref} />
</div>
);
})
// App.js
import MyInput from './components/MyInput';
import { useRef } from 'react';
...
function App() {
const myInputRef = useRef();
const click = () => {
// 하위 컴포넌트의 ref 가져와 출력
console.log(myInputRef.current.value);
}
return <div>
{/* component에 ref를 지정하여, 상위 컴포넌트에서 하위 컴포넌트의 ref를 연결 할 수 있음*/}
<MyInput ref={myInputRef} />
<button onClick={click}>send</button>
</div>
}
👩🏻 하위 컴포넌트 생성 시
export default forwardRef((props, ref) => {...})
형태를 사용하며 input 태그 내에 ref를 등록(<input ref={ref} />
)하고, 상위 컴포넌트에서useRef()
를 통해current.value
와 같은 값을 사용 가능!