개발자

react에서 상태업데이트 로직 자체가 실행이 안되는 경우도 있나요?

2024년 03월 22일조회 132

React에서 Modal이 Modal을 호출하는 다중 Modal 구현중 난제를 만나게 되어 질문을 올립니다 소스의 경우 복붙보다는 github 주소를 남기는것이 좋을것 같아서 github링크로 대체하는점 양해부탁드립니다. https://github.com/graylobo/modalTest (간단해서 clone후 바로 실행가능합니다) 로직에 대해 설명을 하자면 아래와 같습니다. 편의상 음슴체로 하는점 양해부탁드립니다. 1. 전역에서 사용될 기본Modal 을 정의 (BaseModal) 2. BaseModal의 on/off의 경우 recoil로 관리 3. useModalStack 을 사용하여 custom modal (TestModal1,2)을 열수있음 4. custom modal은 다른 custom modal을 호출할수 있으며, modal 호출자는 피호출자의 상태를 공유할수 있음. 즉 SomeComponent가 TestModal1을 호출하고, TestModal1이 또다시 TestModal2를 호출했을때, TestModal2의 상태값을 TestModal1에서 받을수 있으며, TestModal1의 상태값을 SomeComponent에서 받을수 있음 위 기능까지는 문제없이 동작하며, SomeComponent의 경우 TestModal1에서 자신의 로컬상태(inputData)가 있고 확인버튼 클릭시 currentModal.handleConfirm?.(inputData) 가 호출되고 SomeComponent의 handleConfirm에 지정한 콜백로직이 실행되면서 setReceivedData를 통해 receivedData의 상태 업데이트가 TestModal1에서 전달한 inputData로 정상적으로 업데이트가 됨. 또한 SomeComponent가 TestModal1을 호출한 프로세스와 마찬가지로, TestModal1에서 TestModal2 를 호출하고 TestModal2에서 자신의 로컬상태(inputData)가 있고 확인버튼을 클릭하여 currentModal.handleConfirm?.(inputData)를 호출하면 TestModal1의 handleConfirm에 지정한 콜백로직이 실행되면서 TestModal2에서 전달한 inputData를 받는것 까지는 정상적으로 동작하는데 여기서 문제는 TestModal1의 setReceivedData를 통해 receivedData의 상태가 TestModal2에서 전달한 inputData로 업데이트가 되어야 하는데 디버깅시 setReceivedData 자체가 아예실행이 되지않음. react개발하면서 useState의 set함수에 전달하는 콜백함수 자체가 실행이 안되는거는 처음 겪어보고 레퍼런스도 없어서 혹시 저와 동일한 문제를 겪거나 해결방안을 알고 계시는 분이 있다면 조언주시면 매우 감사하겠습니다.

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 2

박정환님의 프로필 사진

제가 잘 이해했는지 확인해 주세요. 결론은 testModal2에서 값을 testModal1로 넘기는데 잘 안들어간다 인건가요? html에서 확인해보니 testModal1에서 testModal2를 오픈할때 testModal1이 사라지는거 같은데 이게 구현하신 것에 맞는 방향인지 한번 확인해보실수 있을까요? 제생각에는 modal1과 modal2가 객체가 살아있어야 서로간의 값 전달이 자유롭지 싶습니다. 그리고 긴 로직을 설명해주시는건 좋은데 알고계시겠지만, 질문은 간결하게 해주셔야 가독성이 좋다는 것을 감안부탁드립니다. 정 중간 과정이 필요하다면, 되도록 상단에 다시 써 주세요.

오지운님의 프로필 사진

오지운

작성자

위드코프2024년 03월 22일

TestModal1에서 TestModal2를 오픈할때 TestModal1이 사라지는것이 아닌 recoil상태인 modalStackStore의 배열에 존재하게 구현을 하였습니다. 즉 만약 TestModal1 이 TestModal2를 오픈하고, TestModal2에서 또 TestModal3을 오픈하면 modalStackStore에는 총 3개(TestModal1~3)의 상태가 저장이 되게 되며, closeModal을 할경우 stack구조(LIFO)로 순차적으로 하나씩 제거되는 형태입니다. 그래서 프로젝트를 실행해보시면 아시겠지만 TestModal2를 닫거나 confirm버튼을 클릭하게 되면 TestModal1 이 다시 나오고 TestModal2가 닫히는 구조입니다! 로직을 자세하게 설명하려하다보니 글이 길어져서 가독성이 안좋아진점은 양해부탁드립니다ㅠ

박정환님의 프로필 사진

박정환

아테모스 시니어 엔지니어2024년 03월 22일

1. recoil로 stack자료구조를 써서 다중 dialog를 구현했다. 2. 그런데 stackDialog2 -> 1로 갈때(close할때) inputData를 통한 값 업데이트가 안된다. 3. setReceived가 실행되지 않는것 같다. 이 정리가 맞다면 다시 한번 봐보겠습니다.

오지운님의 프로필 사진

오지운

작성자

위드코프2024년 03월 22일

1. SomeComponent 에서 useModalStack에 구현한 openModal함수를 통해 TestModal1창 오픈 2. 오픈된 TestModal1에서 다시 openModal함수를 통해TestModal2 오픈 3. 오픈된 TestModal2의 인풋값에 'hello'라는 데이터를 입력후 confirm을 하면 click 핸들러인 currentModal.handleConfirm(inputData) 가 실행되고, TestModal1에서 TestModal2를 오픈하기위해 openModal을 할때 지정한 handleConfirm 콜백이 호출되게됨 4. handleConfirm 의 인자인 data에는 'hello'라는 값이 정상적으로 들어오지만, setReceivedData로직 자체가 실행이 안됨. 실행이 안된다고 판단한 이유는 setReceivedData(()=>{ console.log("data received from TestModal2:", data); return data; }); 위의 setReceivedData의 내부로직에 지정한 console.log 출력이 되지않음. 내부로직 자체가 실행이 안됐으므로 return data도 실행되지않아서 상태업데이트가 되지않는것으로 예상됨. 5. 그런데 이와다르게 TestModal1의 인풋에 값을 입력후 confirm을 하게되면 TestModal1을 오픈한 SomeComponent측의 handleConfirm 콜백이 호출이되고, setReceivedData((prev) => { console.log("data received from TestModal1:", data); return data; }); 위 setReceivedData의 내부로직도 정상적으로 실행돼서 console.log출력도 찍히고 return data로 인해 상태업데이트도 정상적으로 수행됨 위와같은 상황에서 제가 궁금한 부분은 1. SomeComponent에서 TestModal1을 호출하는 로직과 TestModal1에서 TestModal2를 호출하는 로직이 같은데 왜 TestModal1의 setReceivedData은 실행이 안되고, SomeComponent의 setReceivedData은 실행이 되는지? 2. 결론적으로 TestModal1도 SomeComponent처럼 setReceivedData이 실행되도록 해서 상태업데이트가 정상적으로 되게하려면 어떻게 접근해야하는지? 입니다! --------------------------------------------------------------------------- flow를 최대한 간결하게 다시정리해보았는데 어쩔수없이 길어지는점 양해부탁드립니다ㅜ

박정환님의 프로필 사진

박정환

아테모스 시니어 엔지니어2024년 03월 22일

이거 제 경험에 의하면.. typescript에서 useState 선언할때 주의점 있는걸로 알고있습니다. 기본값 세팅이 변경되지 않는 문제였는데.. 제 소스 예전에 했던거 좀 봐야겠네요. (다른 일도 좀 하느라 답신이 늦을수있습니다.)

박정환님의 프로필 사진

박정환

아테모스 시니어 엔지니어2024년 03월 22일

테스트를 좀 해봤습니다. modal3을 만들고 modal2와 소스를 동일화, modal2는 modal1과 동일화 해서 같은 로직들을 실행시켜 봤는데요 결론은 modal3도 수정하기전 modal2와 같이 setState가 실행되지 않습니다. 또한 modal3에 파라미터로 modal2에서 전달한 setIsOpen, closeModal 을 전달시켜 봤고, 버튼 클릭시 modal2로 잘 넘어가는지 확인을 위해 modal2의 'open' 변수를 찍어 보았습니다. ... function TestModal3({ setIsOpen, closeModal }) { ... <button onClick={() => { setIsOpen(false); closeModal(); }} > Test </button> ... 실행했을 때 modal2에서는 아무것도 변경이 일어나지 않았습니다. 추가로, modal2에 '2222'를 입력후 modal3을 열었다가 닫아보면, 그 값도 초기화 됩니다. 이들을 토대로 소스의 구성을 정리해보면 modal1~3은 openModal을 통해 동적으로 생성한 것이고, mater격인 someComponent는 기본적으로 이미 있었던 녀석이라는 차이가 있습니다. 실제로 modal4라는 다른 컴포넌트를 만들어서 someComponent단에 배치시켜 보면 received데이터가 잘 옵니다. 동적으로 생성한 녀석들끼리의 setState가 일어나지 않았습니다. 또한 자신의 child(child라고 하겠습니다. 다음 modal)를 열었다가 닫을시 state가 초기화됨을 알수 있었습니다. 리렌더링은 일어났다는 것이지요. 동적으로 생성하는 modal에서 최대한 자기 자신의 useState를 빼시고 recoil 단으로 관리하거나, 별도의 방안을 한번더 생각해 보심이 좋겠습니다.

오지운님의 프로필 사진

오지운

작성자

위드코프2024년 03월 22일

기본 컴포넌트(SomeComponent)와 모달(TestModal)간에는 setState가 동작하는데, 동적으로 생성한 Modal들간에 setState 가 실행되지않는 이유를 혹시 추측이 되실까요? 상세한 답변 및 의견 감사합니다!

오지운님의 프로필 사진

-

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!