forwardRef
Ref는 Props로 전달할 수 없는 객체 (24.04월 전달할 수 있다고 바뀜!)
Ref를 자식컴포넌트로 전달하려면, 특수한 형태의 컴포넌트가 필요.
=> forwardRef Component
Ref / forwardRef로 Modal을 만들어보자!
- AlertModal을 열고 닫기 위해서는 open, onClose props를 전달해야 함.
- Dialog modal은 dialog.showModal(), dialog.close() 로 제어해야함.
- Props로는 기능 제어가 불가능!
- 함수로 제어 O
<AlertModal.js>
import { forwardRef } from "react";
/**
* export: AlertModal 컴포넌트(함수)/변수/상수 등등을 외부로 공개하기 위한 방법
* import: { AlertModal } from "./path";
*
* export default : AlertModal 컴포넌트(함수)/변수/상수 등등을 외부로 공개하기 위한 방법
* AlertModal.js 파일을 import 했을 때, 대표 컴포넌트(함수)/변수/상수를 공개하는 방법
* 하나의 js 파일에 하나의 export default만 작성.
* 한 파일 내에서 export default를 여러번 작성 X
* import AlertModal, { OtherComponent } from "./path";
*/
// export default function AlertModal({ children }) {
const AlertModal = forwardRef(({ onClose, children }, ref) => {
return (
<dialog className="modal" ref={ref}>
<div className="modal-body">
<section className="modal-close-button" onClick={onClose}>
X
</section>
{children}
</div>
</dialog>
);
});
export default AlertModal;
<Input.js>
import { forwardRef } from "react";
// export default function Input({ id, type, title }) {
const Input = forwardRef(({ id, type, title }, ref) => {
return (
<>
<label htmlFor={id}>{title}</label>
<input type={type} id={id} ref={ref} />
</>
);
});
// }
export default Input;
<RefComponent.js>
import { useRef, useState } from "react";
import AlertModal from "./modal/AlertModal.js";
import Input from "./ui/Input.js";
export function RefComponent() {
const alertModalRef = useRef();
const [item, setItem] = useState([]);
const itemRef = useRef();
const onClickHandler = () => {
const itemValue = itemRef.current.value;
if (itemValue === "") {
console.log(alertModalRef.current);
alertModalRef.current.showModal();
itemRef.current.focus();
return;
}
setItem((prevState) => [itemValue, ...prevState]);
itemRef.current.value = "";
itemRef.current.focus();
};
const onCloseModalHandler = () => {
alertModalRef.current.close();
};
return (
<div className="main-container">
<Input id="text" type="text" title="Text" ref={itemRef} />
<button onClick={onClickHandler}>Save</button>
<hr />
<ul>
{item.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<AlertModal onClose={onCloseModalHandler} ref={alertModalRef}>
<div>
<h3>텍스트를 입력하세요!</h3>
</div>
</AlertModal>
</div>
);
}
<App.js>
import { RefComponent } from "./components/RefComponent";
function App() {
return <RefComponent />;
}
export default App;