혹시 svelte5를 사용하며 이러한 에러를 마주친 적이 있으신가요?
해당 에러는 $effect() 함수에서 발생하는 에러입니다.
$effect() 함수가 무엇인지부터 말씀드리자면
기존 svelte의 반응성 함수인 룬($:)과 동일한 효과를 지니는, 조금 더 업그레이드 된 버전이라 생각하시면 돼요.
상태 변경(예: 외부 라이브러리에 렌더링 또는 외부 라이브러리와 상호 작용)에 따른 응답으로 코드를 실행한답니다.
다만 과도한 사용은 코드를 따라가기 어렵게 만들 수 있으므로 적당히 사용하라는 경고가 존재합니다.
출처 : https://svelte.dev/docs/svelte/$effect
$effect • Docs • Svelte
Effects are what make your application do things. When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside untrack), and re-runs the function when that state later changes. Most of the ef
svelte.dev
그럼 이 에러는 어떻게 해결할 수 있냐면
1. $effect 대신 $state 혹은 $derived를 활용할 수 있다면 사용하기
// 기존 에러 코드
let forInjuryType = false;
$effect(() => {
forInjuryType = $form.customInjuryTypes ? true : false
});
// 수정한 코드
let forInjuryType = $state($form.customInjuryTypes ? true : false);
변수의 상태만 바꾸고싶은거라면 $effect를 쓰지 않고 $state 혹은 $derived를 활용하면 됩니다.
$effect는 기존의 onMount + $ 역할을 하는 셈이라
자칫하면 변수의 상태 변화에 따라 변수를 계속 호출하는 에러가 생길수도 있습니다.
그러니 단순한 처리(예. 변수 상태 변경)는 $state를,
조금 더 로직이 필요하면 $derived를 활용하면 에러가 해결될 겁니다!
1-1. $derived를 활용하기 위해서는
svelte 공식문서에 기본적으로
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
이렇게 간단한 방법이 나와있습니다.
이런식으로 간단한 사칙연산에 활용하는것도 좋지만,
조금 더 복잡한 로직을 원하신다면 $derived.by를 사용하시면 됩니다.
let total = $derived.by(() => {
let total = 0;
for (const n of numbers) {
total += n;
}
return total;
});
공식문서에 따르면 이런 for문을 활용하는 예시가 있습니다.
for문 이외에도 저희가 계속 써오던 $: 룬 함수 뒤에 적은 대부분의 코드들은 저 derived.by로 해결할 수 있습니다.
저는 그래서
let inspectionNameItems = $derived.by(() => {
switch ($form.classification) {
case SEMI_ANNUAL_INSPECTION_CLASSIFICATION.INDUSTRIAL_ACCIDENT.value:
return Object.values(INDUSTRIAL_ACCIDENT_INSPECTION_NAMES);
case SEMI_ANNUAL_INSPECTION_CLASSIFICATION.PUBLIC_ACCIDENT.value:
return Object.values(PUBLIC_ACCIDENT_INSPECTION_NAMES);
case SEMI_ANNUAL_INSPECTION_CLASSIFICATION.LAW_COMPLIANCE.value:
return Object.values(LAW_COMPLIANCE_INSPECTION_NAMES);
default:
return [];
}
});
다음과 같이 활용하였습니다.
주의할점은 $state 혹은 $derived를 쓸때 이를 받을 변수가 필요하다는 점입니다!
2. 컴포넌트의 값이 바뀔때마다 변화를 받고 싶다면 해당 컴포넌트에 onchange 함수를 추가해서 컴포넌트 안에서 해결할 수 있도록 하기
// 기존 에러 코드
$effect(() => {
if ($form.isInhouseContractor !== CHECKLIST_ANSWER_YN.Y.value) {
$form.contractorName = '';
$form.contractorAccidentMgmtNo = '';
}
});
// 수정한 코드
<RadioGroup
...
change={() => {
if ($form.isInhouseContractor !== CHECKLIST_ANSWER_YN.Y.value) {
$form.contractorName = '';
$form.contractorAccidentMgmtNo = '';
}
}}
/>
컴포넌트에서 불러온 값이 바뀔때마다의 변화를 받고싶은거라면
해당 컴포넌트에 Props로 change를 지정해두고 이를 받으면, chage를 컴포넌트의
onValueChange 혹은 onchange처럼 변수의 변경사항을 받아오는 쪽에 넣어서 사용하면 됩니다.
그렇게 되면 앞서 컴포넌트를 활용하는 곳에서 $effect 없이도 변화를 감지해 반응성에 따른 변화를 받아올 수 있습니다.
사실 아직 svelte5가 정상화되지 않은 상태이고,
무엇보다 svelte5를 활용하는 ui 라이브러리들도 정상화되지 않은 상황이라
이 방법으로 해당 에러가 완전히 해결되진 않을 것입니다...
svelte5를 쓰시는 분들의 해결법이 또 있다면 같이 의견 나눠보아요~
'💻 프론트엔드 : Frontend > Svelte' 카테고리의 다른 글
[Superforms] events (0) | 2024.12.12 |
---|---|
[Svelte] 스토어 구독 (1) | 2024.08.31 |