CS/프레임워크&라이브러리

Jotai 상태관리 라이브러리란?

harusari 2024. 3. 2. 17:31

 

Jotai는 Daishi Kato에 의해 만들어졌으며, React 상태 관리의 단순성과 효율성을 개선하려는 목적에서 만들어졌다. Recoil과 MobX와 같은 기존 상태 관리 솔루션들이 제공하는 강력한 기능을 유지하면서도, 단순하고 직관적인 API를 제공하여, 개발자들이 쉽게 상태 관리를 할 수 있도록 설계되었다. Jotai는 일본어로 '상태'를 의미하며, Jotai는 그 사용성과 유연성으로 인해 빠르게 인기를 얻었고, 다양한 규모와 유형의 프로젝트에서 사용되고 있다.

 

jotai vs recoil

 

npm trend에서 recoil과 비교하면 recoil을 역전한 것을 볼 수 있는 꽤 핫한 라이브러리이다.

 


 

1. jotai의 기본 개념과 atom 생성 방법

 

 

Jotai는 atom개념을 사용하며, atom은 작은 데이터를 담고 있다. useAtom을 통해 전역 상태를 관리하고, 생김새는 useState와 유사하다.

useAtom은 배열을 리턴하며, 첫 번째 요소는 atom의 값(value), 두 번째 요소는 atom값을 설정할 함수이다.

 

 

 

기본적인 예제를 살펴보자.

 

 

counter라는 atom을 생성한 뒤, onClick 함수에 atom값을 변경하는 함수 setCounter를 전달해 atom값을 하나씩 늘려주는 간단한 예제이다.

 

 

Jotai를 활용해 테마를 바꾸고 저장하는 방법을 알아보자.

 

'light'라는 string값을 initial value로 갖는 아톰을 생성한 뒤(theme) 버튼에 handleClick 함수를 전달한다. handleClick 함수는 atom값을 변경하는 함수인 setAppTheme을 호출하는 함수인데, 이를 통해 atom값이 light와 dark를 왔다갔다하면서 바뀔 수 있다.

이를 통해 테마를 전역적으로 저장하고 관리할 수 있게 되었다.

 

 


 

2. atomWithStorage를 통해 localStorage에 값을 저장하는 방법

 

 

Jotai의 atomWithStorage를 사용하면 localStorage나 sessionStorage에 값을 저장할 수 있다. 이를 통해 페이지가 새로고침되어도 값이 유지된다.

atomWithStorage는 주로 두 개의 인자를 받는데, 첫 번째 인자에는 key값이, 두 번째 인자에는 초기값(initial value)이 들어간다.

const theme = atomWithStorage('dark', false)를 통해 dark라는 key값과 false라는 value값이 localStorage에 저장된다.

 

더보기

👩🏻‍💻 atomWithStorage의 세 번째 인자

 

jotai atomWithStorage 함수는 추가적으로 세 번째 인자로 옵션 객체를 받을 수 있다. 이 옵션 객체를 통해 스토리지 종류를 지정하거나 저장 및 로딩방식을 커스터마이즈 할 수 있다.

예를 들어, localStorage 대신 sessionStorage를 사용하고 싶다거나 저장되는 값의 직렬화 및 역직렬화 방식을 커스텀하고 싶을 때 옵션 객체를 활용할 수 있다.

 

만약 sessionStorage에 값을 저장하고 싶다면,

 

const themeAtom = atomWithStorage('theme', 'light', {

  storage: sessionStorage

});

 

다음과 같이 세 번째 인자에 {storage: sessionStorage} 를 전달하면 된다.

 

 

활용 예시를 알아보자.

위에서 봤던 theme를 단순히 전역적으로 저장하는 것이 아닌, localStorage에 저장해보자.

이렇게 되면 페이지를 새로고침하거나 종료 후 다시 돌아와도 저장된 테마가 그대로 남아있을 수 있게 된다.

 

LocalStorage에 dark를 key로 가지며 값으로는 boolean을 저장하고 있다.

버튼을 클릭하면 setAppTheme함수가 실행되며 localStorage에 저장된 boolean값이 토글링된다.

 

 


 

3. Read Only atoms

 

ReadOnly atoms는 다른 atom값을 읽기 위해 사용되는 atom이다.

이 atom은 직접적으로 값을 바꿀 수 없는데, 이는 부모 atom에 의존하기 때문이다.

 

부모 아톰에 의존한다는 것은 읽기 전용 아톰이 하나 이상의 다른 아톰(=부모 아톰)의 상태값을 기반으로 자신의 값을 결정한다는 의미이다.

예를 들어 위 코드에서 uppercase 아톰은 textAtom(부모 아톰)의 값에 의존한다. textAtom 값이 변경될 때마다 uppercase 아톰이 그 값을 대문자로 변환한 새로운 값을 가지게 된다. 여기서 uppercase 아톰이 read only 아톰이 된다.

 

이처럼 읽기 전용 아톰은 부모 아톰의 상태에 '의존' 하여 자신의 상태를 도출한다.

직접적으로 값을 변경할 수 없지만, 부모 아톰의 값이 변경되면 그에 따라 자동으로 업데이트되는 특성을 가진다.

이런 방식으로 복잡한 상태 관리 로직을 여러 아톰으로 분산시키면서, 상태 간 의존성을 명확히 할 수 있다.

 

 

 

Read only atom을 사용하는 예시이다.

 

 

위 코드에서 onlineFriends와 offlineFriends가 read only atom인데, friendsStatus atom(부모 아톰)의 값을 읽어와 값에 필터를 정렬한 예시이다. 친구들의 온라인/오프라인 상태에 기반해 친구들을 필터링하고 있다.

 

 

 

즉 정리하자면 read only 아톰은 부모의 상태에 의존한다.

읽기 전용 아톰은 이름 그대로 다른 아톰값을 읽을 수밖에 없으므로 상태변경 함수를 담고 있지 않다.

두 번째 빨간 박스에서 const [uppercaseText] = useAtom(uppercase) 에 상태 변경 함수가 없는 이유이다.

 

 


 

4. Write Only atoms

 

쓰기 전용 아톰(write only atoms)은 read only atom과 반대로 부모 atom의 값을 '수정'할 수 있는 atom이다.

양방향 데이터 바인딩이 가능한데, 파생된 atom의 변경이 부모 atom에도 영향을 줄 수 있고, 반대도 가능하다.

따라서 이러한 atom을 사용할 때는 주의를 기울여야 한다.

 

 

 

 

 

Write only atom은 두 개의 인자를 받는다.

첫 번째 인자는 초기 상태값을 설정하는 부분인데 write only atoms는 이 부분이 null값이 들어간다.

이는 write only atom이 직접적인 상태값을 가지지 않고, 다른 아톰의 상태를 수정하는데에만 사용되기 때문이다.

 

두 번째 인자는 상태를 수정할 수 있는 로직을 담은 함수가 들어간다.

get, set함수를 파라미터로 받을 수 있는데 get함수는 다른 아톰의 현재 상태값을 읽을 때 사용되고, set함수는 다른 아톰의 상태를 수정할 때 사용된다.

 

 

 

예시를 살펴보자.

 

 

uppercase아톰은 여기에서 write only atom으로 사용되었다. (첫 번째 인자에 null값이 들어간 것을 통해 알 수 있다.)

따라서 이 아톰은 직접적으로 상태값을 가지지는 않는다.

대신, 두 번째 인자로 전달된 콜백함수를 통해 textAtom의 값을 대문자로 변경하는 역할을 한다.

 

이렇게 write only 아톰을 사용하면 상태의 업데이트 로직을 별도 아톰으로 분리할 수 있어, 상태 관리 로직을 더 명확하고 유지보수 쉽게 구성할 수 있다. 이 방식은 특히 상태 업데이트가 여러 단계에 걸쳐 발생하거나 복잡한 조건에 따라 달라질 때 유용하다.

 

 

 

조금 더 심화된 예시를 살펴보자.

 

  • `dotsAtom`: 캔버스에 그려진 점들의 위치를 나타내는 배열을 저장하는 아톰이다. 각 점의 위치는 [x,y]형태의 배열로 표현될 것이다.
  • `drawingAtom`: 사용자가 현재 캔버스에 그리고 있는지의 여부(그리기 상태)를 나타내는 boolean 값을 저장하는 아톰이다. 마우스를 누르고 있는 동안 `true`로 설정되고, 마우스를 놓으면 `false`로 설정된다.
  • `handleMouseDownAtom`과 `handleMouseUpAtom`: 이 둘은 Write Only 아톰으로, 사용자의 마우스 다운 및 마우스 업 이벤트에 반응하여 `drawingAtom`의 상태를 각각 `true` 또는 `false`로 변환해준다. 이 아톰들은 직접적으로 상태 값을 가지지 않으며, 다른 아톰의 상태를 변경하는 데 사용된다.
  • `handleMouseMoveAtom`: 사용자가 캔버스 위에서 마우스를 움직이는 동안 새로운 점의 위치를 `dotsAtom`에 추가하는 Write Only 아톰이다. `drawingAtom`이 `true`인 경우에만 작동하고, 실제로 사용자가 그리기 상태일 때 새로운 점의 위치를 추가한다.
  • 이 구조를 통해, jotai 아톰을 사용하여 상태 관리의 복잡성을 줄이고, 캔버스와 같은 상호작용이 필요한 애플리케이션에서 사용자 입력에 따라 동적으로 상태를 업데이트할 수 있다.

 

 

그래서 결국 이렇게 사용할 수 있는데,

 

[ , handleMouseUp] 부분을 보면 알 수 있다시피 write only 아톰은 직접적인 상태값을 가지지 않는다. (null값이 들어감)

handleMouseMoveEvent함수를 통해 update(x, y좌표가 담겨있는 배열) 변수를 전달하고 있는데, 전달된 update배열은

 

위에서 봤던 이 두 번째 인자인 콜백함수의 세 번째 파라미터로 전달되어서 결국 dotsAtom을 업데이트하게 되는 것이다.

 

// 전체 코드

import {atom, useAtom} from 'jotai';

// 캔버스에 그려진 점들의 위치를 관리하는 아톰
const dotsAtom = atom([]);

// 그리기 상태를 관리하는 아톰
const drawingAtom = atom(false);

// 마우스를 누를 때 그리기 시작하는 로직을 관리하는 아톰
const handleMouseDownAtom = atom(null, (get, set) => set(drawingAtom, true));

// 마우스를 놓을 때 그리기를 중지하는 로직을 관리하는 아톰
const handleMouseUpAtom = atom(null, (get, set) => set(drawingAtom, false));

// 마우스 움직임에 따라 점을 추가하는 로직을 관리하는 아톰
const handleMouseMoveAtom = atom(null, (get, set, update) => {
  if (get(drawingAtom)) {
    set(dotsAtom, prevDots => [...prevDots, update]);
  }
});

// SVG 내부에서 점들을 그리는 컴포넌트
const SvgDots = () => {
  const [dots] = useAtom(dotsAtom);
  return (
    <g>
      {dots.map((dot, index) => (
        <circle cx={dot[0]} cy={dot[1]} r="2" fill="#aaa" key={index} />
      ))}
    </g>
  );
};

export default function SvgComponent() {
  const [, handleMouseUp] = useAtom(handleMouseUpAtom);
  const [, handleMouseDown] = useAtom(handleMouseDownAtom);
  const [, handleMouseMove] = useAtom(handleMouseMoveAtom);

  const handleMouseMoveEvent = e => {
    const update = [e.clientX, e.clientY];
    handleMouseMove(update); // handleMouseMove에 update 전달
  };

  return (
    <svg
      width="100vw"
      height="100vh"
      viewBox="0 0 100vw 100vh"
      onMouseDown={() => handleMouseDown()}
      onMouseUp={() => handleMouseUp()}
      onMouseMove={handleMouseMoveEvent}
      style={{background: '#eee'}}>
      <rect width="100vw" height="100vh" fill="none" />
      <SvgDots />
    </svg>
  );
}

 

 

 

그래서 결국 왜 write only 아톰을 사용하는가?

결국 불필요한 리렌더링을 방지하고 로직을 캡슐화하여 유지보수성을 높이는 데에 의의가 있다.

 

 


 

5. Read Write atoms

 

 

read write atom은 이름에서부터 추측할 수 있듯이 읽고 쓰는 것이 모두 가능한 atom이다.

사용의 효용은 하나의 atom에서 읽고 쓰는 것이 모두 가능해 코드 중복을 줄이고 재사용성을 높인다. 또한 상태관련 로직을 중앙집중화하여 관리해야 하는 아톰의 수를 줄이고 코드 가독성을 높인다.

 

 

read write atom의 기본 구조를 살펴보자.

 

write only atom에서는 첫 번째 인자에 null값이 들어갔었는데, read write atom은 첫 번째 인자에 atom값을 읽을 수 있는 로직이 들어간다. 두 번째 인자로는 write only atom과 마찬가지로 쓰기 로직이 들어간다. set함수를 사용하며, 필요에 따라 세 번째 인자를 통해 외부에서 추가 데이터를 받아 로직에 활용할 수 있다.

 

 

 

read write atom의 간단 예시를 살펴보자.

 

여기에서 readWriteAtom은 count 아톰의 값을 읽고 수정할 수 있는 read write atom이다.

get함수를 통해 count atom값을 읽고, 두 번째 파라미터에서는 count atom의 상태를 1 더한 값으로 변경하는 로직이 담겨있다.

 

이를 통해 count 아톰을 작은 범위에 숨기고 readWriteAtom만을 외부에 노출할 수 있는데, 이를 통해 애플리케이션 전체에서 다루어야 할 아톰의 수를 줄일 수 있게 된다.

 

 

 

 

아까 위에서 write only atom할 때 handleMouseMoveAtom을 write only atom에서 read write atom으로 바꿔보자.

 

 

첫 번째 인자가 null에서 dotsAtom 아톰값을 읽을 수 있는 함수로 변경되었다.

이렇게 write only atom에서 read write atom으로 변경하는 것은, 전자는 다른 아톰의 상태를 변경하는 것에 초점을 맞추지만 후자는 상태를 읽을 수도, 변경할 수도 있게 만드는 것이다.

 

결론적으로는 write only atom과 read write atom의 차이는 아톰의 상태를 '외부에 노출' 하고 사용할 수 있는가에 따라 다르다.

read write atom은 상태의 읽기와 쓰기가 모두 지원되지만, write only atom은 상태 변경에 집중되어 있다.

 

 


 

6. atom creator

 

Jotai 라이브러리에서는 아톰을 생성하고 구성하는 로직을 캡슐화하는 함수인 atom creator라는 개념이 있다.

이는 어떠한 특정 기능이 아니라, 아톰을 생성하고 다루는 패턴에 가깝다.

atom creator를 사용하면 불필요한 atom을 중복적으로 만들지 않을 수 있으며 재사용 가능한 상태 관리 로직을 구성할 수 있다.

 

 

 

 

atom creator의 구조를 살펴보자.

 

아톰 크리에이터와 react의 훅은 둘 다 재사용 가능한 로직을 캡슐화하는 매커니즘을 제공한다는 점에서 유사하다.

하지만 react 훅은 컴포넌트의 생명주기와 관련된 로직(상태관리, 부수효과 처리 등)을 관리하지만, 아톰 크리에이터는 아톰을 통한 상태 관리 로직을 캡슐화한다는 데에 차이가 있다.

따라서, 아톰 크리에이터는 jotai를 사용하는 상태관리 패턴에 특화된 훅 '같은' 매커니즘이라고 볼 수 있다.

 

 

 

atom creator의 예시를 살펴보자.

 

createCountIncAtoms라는 atom creator를 만들었다.

이 함수는 initial Value(초기값)를 인자로 받아 이 값을 기반으로 baseAtom을 생성하고 valueAtom은 이 baseAtom 값을 읽는 아톰이다.

incAtom을 통해 baseAtom의 값을 증가시킨다.

마지막으로 valueAtom과 incAtom을 배열로 묶어 리턴하는데, 이를 통해 어떤 값을 받아 +1을 할 수 있는 아톰을 손쉽게 생성할 수 있게 된다.

 

 

 


7. Async atom

 

atom의 종류 중에는 비동기 데이터를 효과적으로 관리할 수 있는 async atom이 있다.

이는 크게 async read 아톰과 async write 아톰 두 가지로 나뉜다.

 

 

 

7-1) async read atom

 

async read atom은 주로 외부 데이터 소스(ex. api 호출)로부터 데이터를 비동기적으로 '읽는' 데에 사용된다.

이는 프로미스를 반환하는데, Jotai가 이 프로미스가 해결될 때까지 기다린 뒤 그 결과를 atom값으로 사용한다.

사용 방식은 async를 읽기 함수 앞에 붙여주면 된다.

 

async read atom은 React의 Suspense와 결합하여 로딩 상태를 관리할 수 있는데, 두 번째 예시처럼 Suspense로 컴포넌트를 감싸게 되면 로딩 상태일 때 fallback 에 전달된 컴포넌트가 렌더링되게 된다.

 

하지만, 이보다는 jotai/utils에 있는 loadable API를 사용하는 게 jotai 방식에 더 부합하다. (아래에서 설명 예정)

 

 

 

7-2) async write atom

 

async write atom은 비동기 작업을 통해 상태를 '업데이트' 할 때 사용된다.

쓰기 함수 내에서 비동기 로직을 실행하고 그 결과에 따른 다른 아톰의 상태를 업데이트한다. 주로 서버에 데이터를 보내고 결과를 '반영' 해야할 때 유용하다. 마찬가지로 쓰기 함수 앞에 async를 붙여 만들 수 있다.

 

async write 함수는 Suspense를 트리거하지 않는다.

더보기

👩🏻‍💻 그럼에도 불구하고, Suspense를 트리거하는 방법

 

Jotai를 사용하면 비동기에서 동기로 전환하는 패턴을 활용해 Suspense를 트리거할 수 있다.

예를 들어, 외부 API로부터 데이터를 비동기적으로 요청하고, 요청이 해결될 때까지 컴포넌트 렌더링을 지연시키고 싶은 경우 아래와 같은 방법을 사용할 수 있다.

 

const request = async () => fetch('https://...').then((res) => res.json());

const baseAtom = atom(0);

const Component = () => {

  const [value, setValue] = useAtom(baseAtom);

  const handleClick = () => {

    setValue(request()); // 요청이 해결될 때까지 Suspense

  };

  // ...

};


위 코드에서 request 함수는 외부 API로부터 데이터를 비동기적으로 가져오는 함수이다.

Component 컴포넌트에서는 setValue를 호출할 때 request함수를 전달한다.

이러한 패턴을 사용하면 request 함수의 비동기 요청이 해결될 때까지 해당 컴포넌트의 렌더링을 Suspense를 사용해 지연시킬 수 있다.

 

 


 

8. 유틸리티

 

8-1) loadable

 

Jotai에서는 비동기 아톰의 상태를 세밀하게 관리할 수 있는 loadable 유틸리티를 제공한다.

이는 아톰의 상태가 로딩 중인지, 데이터를 잘 받아왔는지, 오류가 발생했는지를 나타내는 객체를 반환해준다.

예시에서와 같이 loading, hasData, hasError 상태에 따라 각각의 UI를 렌더링할 수 있게 된다.

 

 

8-2) atomWithReset

 

앞서 살펴봤던 atomWithStorage나 loadable 말고도 유틸리티가 더 있다.

그 중에서 atomWithReset 유틸리티는 아톰을 초기값으로 재설정할 수 있는 아톰을 만들어준다.

useResetAtom 훅을 사용해 아톰을 초기값으로 재설정할 수 있다.

 

예시에서는 counterAtom이라는 아톰을 atomWithReset을 사용해 생성하고 있으며 초기값은 1이다.

Counter 컴포넌트에서 useAtom훅을 사용해 counterAtom의 현재 상태와 업데이트하는 함수를 가져온다. 또한 useResetAtom훅을 사용해 counterAtom의 상태를 초기값(=1)으로 재설정하는 resetCount함수를 가져온다.

 

"Reset" 버튼을 클릭하면 resetCount 함수가 호출되고 counterAtom의 상태가 초기값인 1로 재설정된다.

이를 통해 사용자는 아톰의 상태를 쉽게 초기 상태로 되돌릴 수 있다.

이는 폼 입력 초기화, 상태 관리 로직 초기화 등 다양한 상황에서 유용하게 사용될 수 있다.

 

 

 

8-3) selectAtom

selection -> select  오타입니다

 

selectAtom은 원본 아톰의 값을 기반으로 파생된(derived) 값을 가지는 새로운 아톰을 생성하는 아톰이다.

이를 통해 원본 아톰의 특정 부분만을 선택하고 변형된 값을 다룰 수 있다.

원본 아톰이 업데이트될 때마다 selectAtom에 의해 생성된 파생 아톰도 함께 업데이트된다.

 

두 번째 인자로 선택자 함수(selectorFn)가 들어가는데, 이 함수는 원본 아톰의 값을 받아서 파생된 아톰의 '값' 을 결정한다.

이 함수는 원본 아톰의 값이 변경될 때마다 실행되고, 원본 아톰으로부터 필요한 정보를 추출하거나 변형해서 파생 아톰의 새로운 값을 생성한다.

원본 아톰의 값이 변경되었다는 것을 아는 과정은 (동등성 함수가 없다면) 참조 동등성에 기반한다.

 

세 번째 인자로 동등성 함수(equalityFn)는 파생된 아톰의 이전 값과 새 값이 달라졌는 지 판단하는 함수이다.

이 함수를 사용해 원본 아톰의 값과의 동등성 검사 방식을 커스터마이징 할 수 있다.

즉 깊은 동등성 검사를 수행하는 함수를 세 번째 인자로 전달하여 객체 내용이 실제로 변경되었을 때(깊은 동등성)만 파생된 아톰이 업데이트되게 할 수 있다는 것이다.

이를 통해 내용이 변경되지 않았을 때의 불필요한 상태 업데이트와 컴포넌트 리렌더링을 방지할 수 있다.

 

 

더보기

👩🏻‍💻 참조 동등성, 깊은 동등성에 대해서

 

[참조 동등성 Reference Equality]

 

"참조 동등성"이란 두 변수가 메모리 상에서 동일한 객체를 참조(가리키고 있음)하는지를 기준으로 판단하는 방식이다. , 두 변수가 정확히 같은 메모리 주소를 참조하고 있다면, 이 두 변수는 동등하다고 간주된다. JavaScript에서는 `===` 연산자를 사용하여 이러한 참조 동등성을 확인할 수 있다. 하지만, 이 방식은 객체 내부의 값이 완전히 같더라도, 두 객체가 다른 메모리 주소에 위치하고 있다면(, 두 변수가 서로 다른 객체를 참조하고 있다면) 두 객체를 다르다고 판단한다.

 

예를 들어,

const myAtom = atom({ key: 'value' });

 

// myAtom을 사용하는 컴포넌트에서

const [value, setValue] = useAtom(myAtom);

 

// 객체의 내용은 같지만, 새로운 참조(새 객체)를 생성하여 setValue를 호출하면,

// Jotai는 이를 새로운 값으로 인식하고 아톰을 업데이트한다.

setValue({ key: 'value' }); // 참조가 달라 업데이트 발생

 

 

[깊은 동등성 Deep Equality]

 

"깊은 동등성"은 두 객체의 구조와 내부의 모든 값이 완전히 같은지를 깊이 있게 비교하는 방식이다. 이는 객체의 참조(메모리 주소)가 아닌, 객체가 실제로 가지고 있는 데이터의 내용을 기준으로 동등성을 판단한다. 깊은 동등성을 확인하기 위해서는 `deepEqual`과 같은 깊은 비교 함수를 사용해야 한다

 

 

[깊은 동등성 함수를 사용하는 이유?]

 

애플리케이션에서는 종종 같은 데이터를 가진 새로운 객체를 생성할 때가 있다. 이때, 참조 동등성만을 사용하여 객체를 비교하면, 실제 내용은 같지만 다른 참조(메모리 주소)를 가진 객체를 다르다고 판단하여 불필요한 업데이트나 리렌더링을 유발할 수 있다. 이는 성능 저하의 원인이 될 수 있다.

깊은 동등성 함수를 사용하면, 내용이 실제로 변경되지 않았다면(, 내용이 같다면) 상태 업데이트나 컴포넌트 리렌더링을 방지할 수 있어, 애플리케이션의 성능을 최적화하고 불필요한 연산을 줄일 수 있다. 예를 들어, `selectAtom`을 사용하여 파생된 아톰의 값을 결정할 때 깊은 동등성 함수를 제공하면, 원본 아톰의 값이 내용적으로 변경되었을 때만 파생된 아톰이 업데이트되고, 그 결과로 컴포넌트가 리렌더링된다. 이는 특히 복잡한 객체나 배열을 다룰 때 상태 관리의 정확성과 성능을 동시에 향상시키는 데 도움이 된다.

 

 

 

예시를 살펴보자.

selection -> select 오타임

 

 

선택자 함수인 person => person.name을 통해 원본 아톰인 personAtom에서 name속성만을 가져와 파생된 아톰값을 생성했다.

세 번째 인자로 전달된 deepEqual 함수를 통해 깊은 동등성 검사를 수행하는데, 이를 통해 참조가 다르더라도 객체 내부의 값이 같다면 두 객체를 동일하다고 간주하게 된다.

 

 


 

9. 라이브러리와의 통합

 

 

 

Jotai는 다양한 제3자 라이브러리와의 통합을 지원한다.

 

 

 

9-1) Immer 라이브러리

 

atomWithImmer는 Immer를 통해 불변성을 자동으로 관리해주어서, 상태를 직접적으로 변경할 수 있다.

객체의 값을 변경하려면 스프레드 연산자 등을 활용해야 하는데, 이러한 방식을 사용해 값을 가변적으로 변경하는 코드를 작성해도 불변성이 유지된다.

 


 

출처

https://tutorial.jotai.org/quick-start

 

'CS > 프레임워크&라이브러리' 카테고리의 다른 글

ZUSTAND  (2) 2024.05.22
jquery를 사용하지 않게 된 이유  (0) 2024.05.20
[React] 18버전의 추가된 새로운 기능 (step- 2)  (0) 2024.02.24
React v18 - 2  (0) 2024.02.24
React v18 - 1  (0) 2024.02.17