본문 바로가기
일지/헬키

헬키 개발일지 8. 2024 06 29 React의 복잡한 hooking

by 리나그(ReenAG) 2024. 6. 30.
728x90
반응형

react-native도 결국은 react를 기반으로 돌아가다보니까 react를 알고 들어가야 한다는 건 눈 감고도 알 수 있는 사실이다. 그래도... 100% 알고서 개발을 시작하는 사람이 어디있겠는가? 안 되는게 생기고, 그거 고치려고 찾아서 하다보니까 배우는 것이 사실은 더 많다.

어떻게든 되는 코드 찾겠다고. 오늘이 그런 날인 것 같다.

 

아래가 결론적인 코드다.

const expand = useCallback((memo: string, onSaveMemoHandler: (memo:string) => void) => {
    //왜 인지는 모르겠지만 이렇게 prev값을 이용해서 함수형식으로 setState를 처리하면
    //제대로 동작이됩니다... 근데 왠지는 모름...?????
    setMemo((prev) => { return memo });
    setHandler((prev: any) => { return onSaveMemoHandler });
    ref.current?.expand();
}, []);

 

expand는 위의 상위 컴포넌트의 ref에서 불릴 수 있는 함수로, 내가 만든 modal을 화면에 올려주는 역할을 한다. expand안의 ref는 완전 껍데기만 있는 BaseModal이란 녀석의 expand함수를 불러준다. Modal을 애니메이션 적용해서 그때마다 만드는 건 멍청한 짓이기 때문에 common 폴더 안쪽에다 정리해두었다. 기존의 래퍼런스로 삼았던 것의 "BottomSheet"를 개조해서 만들었는데 잘 동작하는 걸 봐선 그 사람이 코드를 잘 짜둔 것 같다. 흠흠... 뭐 내가 모든 걸 다짜는 것보다는 차라리 이런게 나을 때가 있잖은가? 

 

중요한 flow는 이렇다.

1. 상위 컴포넌트 Home에서 Modal에 관한 ref를 만듦(이건 Modal마다 따로 만들었음~)

2. 그럼 커스텀Modal(특수한 기능이 있는 Modal)에서는 forwardRef를 이용해서 ref를 우선 받아옴

3. 그렇게 가져온 forwaredRef와 자기 아래의 BaseModal을 조정할 ref를 둘 다 조정가능, 이를 이용해서 expand를 만듦

4. expand를 만들어서 아래의 BaseModal을 실제로 expand하는 것 말고도 memo를 받아오고 저장하기를 누를때의 handler를 만드는 등의 추가적인 조작을 할 수 있음

5. useImpermativeHandle을 이용해서 이렇게 바뀐 expand를 실제로 ref에 적용~

freedom으로 만든 관계도다

 

나도 뭐 이렇게 복잡하게 해야하난 싶지만, 이렇게 하지 않고 상위 컴포넌트의 state를 바꾸어서 Modal의 기능을 구현하는 이상한 짓을 한 적도 있는데 그거에 비해서는 flow가 간단해졌다. ref하나로 퉁칠 수도 있고 Home 컴포넌트도 깔끔해졌고 버그도 좀 줄어들었을 것이다.

 

이게 이상적인 상황이었는데... 정작 하고 싶었던 expand에서 setState가 되지 않는 문제가 발생했다. ㅠ

기존에는 코드가 이랬다.

const expand = useCallback((memo: string, onSaveMemoHandler: (memo:string) => void) => {
    //맞왜틀?
    setMemo(memo);
    setHandler((onSaveMemoHandler);
    ref.current?.expand();
}, []);

이론적으로는 위와 다르지는 않은 것 같은데? 도대체 무슨 문제인지 모르겠지만 그냥 위의 코드는 되는데 아래껀 안된다... 나도 이유를 모른다.

제일 말이 될 만한 설명으로는... setState가 함수형식으로 주어지면 바로 state를 바꾸기 보다는 useEffect를 쓴 것 마냥 한 템포 쉬어서 다음 render가 가능한 때에 불려 제대로 업데이트가 되었다. 정도일지도. 모르겠다~

 

막상 블로그 글을 적다보니까 생각난 발상인데, useCallback을 그냥 안 쓰면 되는 일 아닌가 싶다.

...

하...

하여간에 테스트는 해봐야지.

useCallBack은 기본적으로는 useMemo처럼 memoize를 위해서 사용한다는 사실을 이번에 이걸 들여다보면서 처음 알았다.

https://stackoverflow.com/questions/55738134/should-i-include-setstate-in-usecallbacks-array-of-dependencies

 

Should I include setState in useCallback's array of dependencies?

const [active, setActive] = useState(false); const onActiveChanged = useCallback( isActive => () => { // do something setActive(isActive); }, [setActive...

stackoverflow.com

 

아래의 글도 조금씩 참고했는데 혹시라도 더 많은 정보를 찾는 사람이 있다면 보면 좋을 것 같다.

 

https://velog.io/@pon06188/Warning-Cannot-update-a-component-A-while-rendering-a-different-component-B.-To-locate-the-bad-setState-call-inside-B-follow-the-stack-trace-as-described-in-에러-해결

 

Warning: Cannot update a component (`A`) while rendering a different component (`B`). To locate the bad setState() call inside `

이 에러는 A 컴포넌트를 변경할 때 B 컴포넌트를 업데이트 할 수 없다는 내용이다. 리액트 깃허브에서 친절하게 에러가 난 부분을 설명해주고 있다출처 : facebook React GitHub(https://github.com/facebook/rea

velog.io

 

https://velog.io/@dongdong98/React-Hook-총정리

 

React Hook 총정리

React 16.8 버젼에 추가된 공식 라이브러리Class형 컴포넌트에서만 쓸 수 있었던 state와 life cycle을 Function형 컴포넌트에서도 사용 가능JavaScript의 클로저(Closer) 를 이용현재 공식문서에서는, Class형 컴

velog.io

 

하여간에 일단 구현되었으니까 된거야! 우히히

728x90
반응형