usestore-ts

์‹œ๋“œ์›จ์ผ์—์„œ ๋งŒ๋“  ์ „์—ญ ์ƒํƒœ๊ด€๋ฆฌ ๋„๊ตฌ

์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด decorator, metadata๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ํŠน์ง•!

Install

npm i usestore-ts

๋‚ด๋ถ€์ ์œผ๋กœ typescript decorator๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ tsconfig.json ์˜ต์…˜๋“ค์„ ์ˆ˜์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

  "experimentalDecorators": true,
  "emitDecoratorMetadata": true,

Usage

๊ธฐ์กด์— TSyringe + reflect-metadata๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“  ๊ฐ„๋‹จํ•œ ์Šคํ† ์–ด๋ฅผ usestore-ts ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•ด๋ณด์ž.

CounterStore

usestore-ts์—์„œ ์ œ๊ณตํ•˜๋Š” Store ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๊ธฐ์กด ObjectStore ํด๋ž˜์Šค๋ฅผ ๋Œ€์ฒดํ•œ๋‹ค.

์ฆ‰, ObjectStore๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ (๊ตฌ๋… ๊ด€๋ฆฌ, ์ƒํƒœ๋ณ€๊ฒฝ์„ ์•Œ๋ฆฌ๋Š” ์ž‘์—… ๋“ฑ)์„ ๋‹ด๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ

import { singleton } from 'tsyringe';
import { Store, Action } from 'usestore-ts';

/* 
 * ์‹ฑ๊ธ€ํ†ค ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์Šคํ† ์–ด ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ณด๋‹ค ์ƒ์œ„์— ๋‘์ž.
 * ์‹ฑ๊ธ€ํ†ค์„ ๋จน์€ ํด๋ž˜์Šค๋ฅผ ์Šคํ† ์–ด ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด์Šˆ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ
 */ 
@singleton()
@Store()
export default class CounterStore {
  counter = 0;
  // ์•ก์…˜ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” publish ๋ฉ”์„œ๋“œ๋ฅผ ๋จธ๊ธˆ๊ณ  ์žˆ๋‹ค.
  @Action()
  increase(step = 1) {
    this.counter += step;
  }

  @Action()
  decrease(step = 1) {
    this.counter -= step;
  }
}

useCounterStore

usestore-ts๊ฐ€ ์ œ๊ณตํ•˜๋Š” useStore ํ›…์œผ๋กœ ๊ธฐ์กด useObjectStore๋ฅผ ๋Œ€์ฒด

forceUpdate ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋จธ๊ธˆ๊ณ  ์žˆ๋‹ค.

import { container } from 'tsyringe';
import { useStore } from 'usestore-ts';

import CounterStore from '../stores/counterStore';

export default function useCounterStore() {
  const store = container.resolve(CounterStore);

  return useStore(store);
}

CounterController.tsx

useStore(store)๋Š” [state, store] ํ˜•ํƒœ์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

state๋กœ ์Šคํ† ์–ด์— ๋‹ด๊ธด ๊ฐ’๋“ค์„ ์‚ฌ์šฉ

store๋Š” ์Šคํ† ์–ด์— ๋‹ด๊ธด ์•ก์…˜ api๋“ค์ด ๋‹ด๊ฒจ ์žˆ๋‹ค.

import useCounterStore from '../hooks/useCounterStore';

export default function CounterController() {
  const [, store] = useCounterStore();

  const handleClickIncrease = (step?: number) => () => {
    store.increase(step);
  };

  const handleClickDecrease = (step?: number) => () => {
    store.decrease(step);
  };

  return (
    <div>
      <button type="button" onClick={handleClickIncrease(10)}>
        Increase 10
      </button>
      <button type="button" onClick={handleClickIncrease()}>
        Increase
      </button>
      <button type="button" onClick={handleClickDecrease(10)}>
        Decrease 10
      </button>
      <button type="button" onClick={handleClickDecrease()}>
        Decrease
      </button>
    </div>
  );
}

Counter.tsx

import useCounterStore from '../hooks/useCounterStore';

export default function Counter() {
  const [{ counter }] = useCounterStore();

  return (
    <div>
      <p>{`counter: ${counter}`}</p>
    </div>
  );
}

Last updated