아카이브

[Solid] Syntax | 05. onMount & onCleanup 본문

Frontend/SolidJS

[Solid] Syntax | 05. onMount & onCleanup

Rayi 2024. 6. 20. 17:59

onMount & onCleanup은 컴포넌트가 생성 & 소멸할 때 한 번 호출되는 특별한 effect 호출입니다.

1. onMount()

아래는 photos signal에 저장된 이미지 파일들을 For 컴포넌트를 이용해 하나씩 불러오는 코드입니다.

import { render } from "solid-js/web";
import { createSignal, onMount, For } from "solid-js";
import "./styles.css";

function App() {
  const [photos, setPhotos] = createSignal([]);
	
  // 각 이미지파일들을 비동기적으로 불러와 photos signal 배열에 추가합니다.
  const fetchPhotos = async () => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);
    setPhotos(await res.json());
  };

  fetchPhotos();
  
  return <>
    <h1>Photo album</h1>

    <div class="photos">
      <For each={photos()} fallback={<p>Loading...</p>}>{ photo =>
        <figure>
          <img src={photo.thumbnailUrl} alt={photo.title} />
          <figcaption>{photo.title}</figcaption>
        </figure>
      }</For>
    </div>
  </>;
}

render(() => <App />, document.getElementById('app'));

 

만약 fetchPhotos()를 직접 실행할 경우,

1. 컴포넌트가 DOM에 랜더링되기 전에 함수가 실행되어 예상하지 못한 결과가 출력 될 수 있으며

2. App 컴포넌트가 다시 랜더링될 경우, fetchPhotos도 불필요하게 재실행될 수 있다는 문제가 있습니다.

 

onMount() 함수는 App 컴포넌트 생성시, DOM에 랜더링 된 후에 한 번만 실행되기 때문에,

이 두 가지 문제들을 해결할 수 있습니다.

import { render } from "solid-js/web";
import { createSignal, onMount, For } from "solid-js";
import "./styles.css";

function App() {
  const [photos, setPhotos] = createSignal([]);

  // App이 생성될 때 onMount()를 실행합니다.
  onMount(async () => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);
    setPhotos(await res.json());
  });

  return <>
    <h1>Photo album</h1>

    <div class="photos">
      <For each={photos()} fallback={<p>Loading...</p>}>{ photo =>
        <figure>
          <img src={photo.thumbnailUrl} alt={photo.title} />
          <figcaption>{photo.title}</figcaption>
        </figure>
      }</For>
    </div>
  </>;
}

render(() => <App />, document.getElementById('app'));

2. onCleanup()

아래는 1초마다 숫자를 증가시키는 timer를 Update 버튼을 이용해 on/off하는 코드입니다.

import { render } from "solid-js/web";
import { createSignal, onMount, onCleanup } from "solid-js";

function Timer() {
  let interval;
  onMount(() => {
    interval = setInterval(() => console.log('interval'), 1000);
  });
  return (
    <div>Timer</div>
  );
}

function App() {
  const [count, setCount] = createSignal(0);

  return (
    <div>
      {count() % 2 === 0 && <Timer />}
      <button onClick={() => setCount(() => count() + 1)}>Update - {count()}</button>
    </div>
  );
}

render(() => <App />, document.getElementById('app'));

Timer를 켜면 정상적으로 로그가 출력되나, Timer를 껐다가 다시 키면 로그가 한 번에 두 번 씩 출력되는 것을 확인할 수 있습니다.

이는 Timer 컴포넌트를 없앤 뒤 다시 생성하여 onMount() 함수가 두 번 실행 되었기 때문입니다.

onCleanup() 함수를 이용해 Timer가 소멸될 때 clearinterval을 실행하면 이 문제를 해결할 수 있습니다.

import { render } from "solid-js/web";
import { createSignal, onMount, onCleanup } from "solid-js";

function Timer() {
  let interval;
  // Timer가 생성될 때 실행됩니다.
  onMount(() => {
    interval = setInterval(() => console.log('interval'), 1000);
  });
  // Timer가 소멸할 때 실행됩니다.
  onCleanup(() => {
  	if(interval) {
      clearInterval(interval);
    }
  });
  return (
    <div>Timer</div>
  );
}

function App() {
  const [count, setCount] = createSignal(0);

  return (
    <div>
      {count() % 2 === 0 && <Timer />}
      <button onClick={() => setCount(() => count() + 1)}>Update - {count()}</button>
    </div>
  );
}

render(() => <App />, document.getElementById('app'));
728x90

'Frontend > SolidJS' 카테고리의 다른 글

[Solid] Syntax | 07. ref  (0) 2024.06.21
[Solid] Syntax | 06. classList  (0) 2024.06.21
[Solid] Syntax | 04. Control Flow  (0) 2024.06.20
[Solid] Syntax | 03. Memo  (0) 2024.06.20
[Solid] Syntax | 02. Effect  (0) 2024.06.20
Comments