여러가지 고객이 원하는 페이지를 만들다보면 새창을 열어서 데이터를 받아야 할 때가 있다.
예전에 Spring에서는 parent. 아니면 window.opener 로 전달해줬던거 같은데 React에선 쓸수없다.(왜 그런지는 사실 잘 모른다.)
GPT야 React에서 window.open으로 팝업창으로 띄워서 작성한 데이터를 받는방법을 알려줘
부모창
//...
const [data, setData] = useState(null);
const handleOpenPopup = () => {
const popup = window.open('/popup', 'Popup', 'width=600,height=400');
const _timer = setInterval(() => {
if(popup.closed){
if(popup.dataFromPopup{
setData(popup.dataFromPopup);
}
}
}, 500);
}
자식창
const sendToParent = () => {
if(window.opener){
window.opener.dataFromPopup = inputValue;
window.close();
}
}
해보진 않았다. setInterval로 사용하는 부분이어서 성능이 안좋지 않을까 하는 생각이다.
간단히 구현할때는 좋아보인다.
window에 이벤트중에 'storage'를 이용하는 방식이 있다.
storage 이벤트는 localStorage, sessionStorage 의 변경이 일어나면 이벤트가 발생한다.
부모창
//...
//store이벤트를 받아서 처리해주는 부분을 만든다.
const storageEvent = e => {
const popupData = localStroage.getItem('popup');
if(popupData){
window.removeEventListener('storage', storageEvent);
}
}
const handleOpenWindow = () => {
window.open('/popupDetail', '팝업', '');
localStorage.removeItem('popup');
window.addEventListener('storage', storageEvent);
}
return (
<>
<button onClick={handleOpenWindow}>OPEN!</button>
</>
)
자식창
//...
const handleClick = () => {
const _saveData = {
age: 10,
name: 'name'
}
localStorage.setItem('popup', JSON.stringify(_saveData);
window.close();
}
위에서 어차피 storage 이벤트를 판단하는거라면, 상태관리에서 데이터를 저장할때 localStorage나 SessionStorage를 활용할수 있다고 알고있어 jotai라는 라이브러리를 사용해보기로 했다.
atoms.js
export const userDataAtom = atomWithStorage('userData', null);
부모창
//...
const [userData, setUserData] = useAtom(userDataAtom);
//...
useEffect(() => {
console.log('userData', userData);
},[userData]);
자식창
//...
const [userData, setUserData] = useAtom(userDataAtom);
//...
const handleSave = () => {
const _saveData = {
//...
}
//...
setUserData(JSON.stringify(_saveData));
window.close();
}
끗!