constate 활용법과 이유
현재 발전왕 비즈에선 state 값을 전역으로 관리하는 라이브러리를 아예 사용하고 있지 않다.
이유는 잘모르겠지만 예전에 개인적으로 redux thunk의 경우 사용해본 결과 사용방법이 복잡하긴 했다.
현재 회사에선 context api의 개량형 constate을 사용하기로 했다. constate은 기존 context api의 리랜더링 해결한다. context api의 경우 의존성이 있는 컴포넌트가 리랜더링 되는 문제가 있었다.
const App = () => {
return (
<ModalProvider>
<ModalToggleButton />
<Modal />
</ModalProvider>
)
}
const ModalToggleButton = () => {
const [, setShow] = useContext(ModalContext);
return <button onClick={() => setShow((state) => !state)}>모달토글</button>;
}
const Modal = () => {
const [show] = useContext(ModalContext);
return show ? <div>나 모달</div> : null;
}
여기에서 ModalToggleButton을 눌렀을 때 Modal만 리랜더링되면 다행인데 useContext는 modalContext를 사용하는 컴포넌트, 즉 의존성이 있는 컴포넌트를 모두 리랜더링한다. 위의 예제와 같이 간단한 거면 문제가 아닌데 좀만 복잡해져도 큰 문제가된다.
그래서 이를 방지하는 constate을 현재 회사에선 채택하였다.
constate의 경우에도 provider가 있다.
import { useState } from "react";
import constate from 'constate';
const useRandomPicker= () => {
const [result, setResult] = useState(null);
return { result, setResult };
}
const [RandomPickerProvider, useResultValue, useResultUpdate] = constate(
useRandomPicker,
value => value.result, // becomes useResultValue
value => value.setResult // becomes useResultUpdate
);
const Result = () => {
const result = useResultValue();
}
const Control = () => {
const setResult = useResultUpdate();
}
constate의 경우 리랜더링이 안된다고한다. 그리고 좋은 점은 result라는 스테잇값을 지속적으로 사용할 수있다는 점이다.
얼핏 보면 꽤 괜찮은 상태 관리 라이브러리 같다.
하지만 실제로 사용해본 결과
작은 문제 하나와 고질적인 provider 지옥 문제가 있었다.
작은 문제는 Provider를 감싼 컴포넌트에서는 constate를 사용하지 못한다는 것이었다.
그래서
index.tsx
<Provider>
<Content/>
</Provider>
이렇게 따로 의미없이 프로바이더로 감싸는 컴포넌트를 써야한다. 이부분은 해결 중이다.
둘째로는 조금만 관리하는 state값이 많아져도 provider 내부가 복잡해지고 관리하기가 힘들다. 보안상 코드는 못보여주지만
const [RandomPickerProvider, useResultValue, useResultUpdate] = (
useRandomPicker,
value => value.result, // becomes useResultValue
value => value.result2, // becomes useResultValue2
value => value.result3, // becomes useResultValue3
value => value.result4, // becomes useResultValue4
value => value.result5, // becomes useResultValue5
value => value.setResult // becomes useResultUpdate
value => value.setResult2 // becomes useResultUpdate2
value => value.setResult3 // becomes useResultUpdate3
value => value.setResult4 // becomes useResultUpdate4
value => value.setResult5 // becomes useResultUpdate5
);
위의 예제를 보면 쉽게 이해할 수 있다. provider의 위치 기준으로 스테잇 값을 관리하다보니 provider가 감싼 컴포넌트에서 위와 같이 수 많은 값을 관리해야한다.
그리고 provider의 위치를 어디에 설정해야하는지 참 애매하다. 컴포넌트별로 따로 해놓았는데 나중에 다른 컴포넌트에서 이 컴포넌트의 스테잇 값을 컨트롤해야하게 되면 어떻게하는가?
<RaceProvider>
<StartProvider>
<Start/>
</StartProvider>
<EndProvider>
<End/>
<EndProvider/>
</RaceProvier>
위의 예에서 start provider에서 관리하던 스테잇 값을 end 기능을 추가하면서 End컴포넌트에서도 필요하게 되면 어떻게 해야하는가? RaceProvider에 이 스테잇을 모두 옮겨야하는가? 이처럼 비 효율적인게 없다.
현재 redux에 대해선 고려사항이 아닌듯해서 나로서는 많이 아쉽다. 최근에 toolkit추가로 react hook대응이 된다고 하던데 한번 해보고 싶다. 개인 프로젝트에서 한번 적용시켜봐야겠다.
참고 : https://ddus.site/constate
Author And Source
이 문제에 관하여(constate 활용법과 이유), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@greyzero/constate-활용법과-이유저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)