Jotai Tutorial - Read Write atom

taez·2023년 3월 26일
0

Jotai tutorial

목록 보기
5/7
post-thumbnail

들어가며

이번 포스트는 지난 포스트에서 이어지는 글입니다.

지난 포스트 복습

// Primitive atom
const dotsAtom = atom([]);
const isDrawingAtom = atom(false);

// Write only atom
const handleMouseDownAtom = atom(
	null,
  	(get, set) => set(isDrawingAtom, true)
);

const handleMouseUpAtom = atom(
  	null,
  	(get, set) => set(isDrawingAtom, false)
);

const handleMouseMoveAtom = atom(
	null,
  	(get, set, update: Point) => {
      if(get(isDrawingAtom)) {
      	set(dotsAtom, (prev) => [...prev, update]);
      }
    }
)
const SvgDots = () => {
	const [dots] = useAtom(dotsAtom);
  	return (
      <g>
        {dots.map(([x, y], index) => (
          <circle cx={x} cy={y} r="2" fill="#aaa" key={index} />
        ))}
      </g>
  );
};

const SvgRoot = () => {
  	const [, handleMouseMove] = useAtom(handleMouseMoveAtom);
  	const [, handleMouseDown] = useAtom(handleMouseDownAtom);
  	const [, handleMouseUp] = useAtom(handleMouseUpAtom);
  	return (
      <svg
        width="100vw"
      	height="100vh"
      	viewBox="0 0 100vw 100vh"
        onMouseDown={handleMouseDown}
        onMouseUp={handleMouseUp}
        onMouseMove={(e) => {
          handleMouseMove([e.clientX, e.clientY]);
        }}
      >
        <rect width="100vw" height="100vh" fill="#eee" />
        <SvgDots />
      </svg>
  );
};

Read Write atom

이전 포스트까지 잘 따라오셨다면 이번 포스트는 쉬어가는 시간이다.
Read only atom과 Write onle atom을 합쳐놓은 것이 바로 Read Write atom이다.

Read Write atom의 기본 형태는 다음과 같다.

const priceAtom = atom(10)
const readWriteAtom = atom(
  	(get) => get(priceAtom) * 2,
  	(get, set, newPrice: number) => {
  	  set(priceAtom, newPrice / 2)
 	}
)

atom()의 첫 번째 파라미터로 get을 argument로 가지는 read function을 넘기고
두 번째 파라미터로 get, set, update 를 argument로 가지는 write function을 넘기면 된다.

위의 readWriteAtom은 priceAtom * 2에 해당하는 값을 가지고 있고
newPrice를 set 할 시 newPrice/2 에 해당하는 값을 priceAtom에 set 한다.

사실 여기서 설명은 끝이지만 뭔가 심심하니 이전 포스트에서 만든 Write only atom들 중 하나를 Read Write atom으로 바꿔보자.

만들기

// Write Only atom
const handleMouseMoveAtom = atom(
	null,
  	(get, set, update: Point) => {
      if(get(isDrawingAtom)) {
      	set(dotsAtom, (prev) => [...prev, update]);
      }
    }
)

위의 handleMouseMoveAtom에 read function을 추가해주면 Read Write atom이 된다.
대충 현재 찍혀있는 dot 들의 개수를 가져오는 함수를 넣어보자.

// Read Write atom
const handleMouseMoveAtom = atom(
	(get) => get(dotsAtom).length,
  	(get, set, update: Point) => {
      if(get(isDrawingAtom)) {
      	set(dotsAtom, (prev) => [...prev, update]);
      }
    }
)

그리고 SvgRoot를 다음과 같이 바꿔주면..

const SvgRoot = () => {
  const [, handleMouseUp] = useAtom(handleMouseUpAtom);
  const [, handleMouseDown] = useAtom(handleMouseDownAtom);
  // Read Write Atom 사용하기
  const [dotsCount, handleMouseMove] = useAtom(handleMouseMoveAtom);
  return (
    <svg
      width="100vw"
      height="100vh"
      viewBox="0 0 100vw 100vh"
      onMouseDown={handleMouseDown}
      onMouseUp={handleMouseUp}
      onMouseMove={(e) => {
        handleMouseMove([e.clientX, e.clientY]);
      }}
    >
      <rect width="100vw" height="100vh" fill="#eee" />
      <text x="3" y="12" font-size="12px">
        dots: {dotsCount}
      </text>
      <SvgDots />
    </svg>
  );
};

정리

const primitiveAtom = atom(initialValue);
const derivedReadOnlyAtom = atom(readFunction);
const derivedWriteOnlyAtom = atom(null, writeFunction);
const derivedReadWriteAtom = atom(readFunction, writeFunction);

const [value, setValue] = useAtom(primitiveAtom);
const [readValue] = useAtom(derivedReadOnlyAtom);
const [,updateValue] = useAtom(derivedWriteOnlyAtom);
const [readVal, updateVal] = useAtom(derivedReadWriteAtom);

참조

https://jotai-tutorial.netlify.app/quick-start/read-write-atoms
https://egghead.io/lessons/react-prevent-rerenders-and-add-functionality-with-jotai-write-only-atoms

profile
흔하지 않은 개발자

0개의 댓글