Custard Library

가장 최근 실험중인 라이브러리를 소개합니다.

@custardcream/very-simple-store

레포지토리 링크

자세한 구현 히스토리

샘플 코드 (동기 데이터)

import {
  addStoreNode,
  addStoreSelectorNode,
  StoreRoot,
  useStoreNode,
  useStoreNodeGetter,
  useStoreSelectorNode,
} from "@custardcream/very-simple-store";
 
export function Sample() {
  return (
    <StoreRoot>
      <Children1 />
      <Children3 />
      <Children4 />
      <SelectorDisplay />
    </StoreRoot>
  );
}
 
const testCounter1Node = addStoreNode({
  initialState: 0,
  key: "testCounter1",
});
 
const testCounter2Node = addStoreNode({
  initialState: 10,
  key: "testCounter2",
});
 
const sumSelectorNode = addStoreSelectorNode({
  key: "testCounterSum",
  selector: ({ get }) => {
    const testCounter = get(testCounter1Node);
    const testCounter2 = get(testCounter2Node);
    return testCounter + testCounter2;
  },
});
 
const Children1 = () => (
  <div>
    Children1
    <Children2 />
  </div>
);
 
const Children2 = () => {
  const value = useStoreNodeGetter(testCounter1Node);
 
  return (
    <div>
      Children2
      <div>testCounter1: {value}</div>
    </div>
  );
};
 
const Children3 = () => {
  const [value, setValue] = useStoreNode(testCounter1Node);
 
  const handleClick = () => setValue((prev) => prev + 1);
 
  return (
    <div>
      <div>Children3</div>
      <button onClick={handleClick}>Increment Button</button>
      <div>testCounter1: {value}</div>
    </div>
  );
};
 
const Children4 = () => {
  const [value, setValue] = useStoreNode(testCounter2Node);
 
  const handleClick = () => setValue((prev) => prev + 1);
 
  return (
    <div>
      <div>Children4</div>
      <button onClick={handleClick}>Increment Button</button>
      <div>testCounter2: {value}</div>
    </div>
  );
};
 
const SelectorDisplay = () => {
  const { value: sum } = useStoreSelectorNode(sumSelectorNode);
 
  return <div>selectorValue: {sum}</div>;
};

실행결과

버튼을 클릭하면 위의 숫자가 증가합니다.

렌더링 확인을 위해 렌더된 컴포넌트에는 주황색 outline 깜빡임이 추가됩니다.

Store의 현재 상태
{
    "selectors": {},
    "state": {}
}
Sample (버튼을 눌러보세요)
Children1
Children2
testCounter1: 0
Children3
testCounter1: 0
Children4
testCounter2: 10
SelectorDisplay
selectorValue:

샘플 코드 (비동기 데이터)

import {
  addStoreNode,
  addStoreSelectorNode,
  StoreRoot,
  useStoreNode,
  useStoreSelectorNode,
} from "@custardcream/very-simple-store";
import React from "react";
 
export function AsyncSample() {
  return (
    <StoreRoot>
      <Children1 />
      <Children2 />
    </StoreRoot>
  );
}
 
const storeNode = addStoreNode({
  initialState: 0,
  key: "storeNode",
});
 
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
 
const asyncSelectorNode = addStoreSelectorNode({
  key: "asyncSelectorNode",
  selector: async ({ get }) => {
    const testState = get(storeNode);
 
    await wait(2000);
 
    return testState + 1;
  },
});
 
const Children1 = () => {
  const [value, setValue] = useStoreNode(storeNode);
 
  const handleClick = () => setValue((prev) => prev + 1);
 
  return (
    <div>
      Children1
      <button onClick={handleClick}>Increment Button</button>
      <div>storeNode: {value}</div>
    </div>
  );
};
 
const Children2 = () => {
  const { value, isLoading, currentlyLoadingCount } = useStoreSelectorNode(asyncSelectorNode);
 
  return (
    <div>
      Children2
      <div>currentlyLoadingCount: {currentlyLoadingCount}</div>
      <div>isLoading: {JSON.stringify(isLoading)}</div>
      <div>asyncSelectorNode: {value}</div>
    </div>
  );
};

실행결과

버튼을 누르면 storeNode가 동기적으로 갱신되고 2초 후 asyncSelectorNode가 비동기적으로 갱신됩니다.

Store의 현재 상태
{
    "selectors": {},
    "state": {}
}
Sample (버튼을 눌러보세요)
Children1
storeNode: 0
Children2
currentlyLoadingCount: 0
isLoading: true
asyncSelectorNode: