usestore-ts

ํ•™์Šตํ‚ค์›Œ๋“œ

  • usesotre-ts

  • ์‹œ๋“œ์›จ์ผ์—์„œ ์ œ์ž‘ํ•œ React state management library

๊ฐ„๋‹จํ•œ, ํ•˜์ง€๋งŒ TypeScript ์ „์šฉ์ธ, React ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ usestore-ts ์ž…๋‹ˆ๋‹ค. React ์™ธ๋ถ€(์ •ํ™•ํžˆ๋Š” UI ๋ ˆ์ด์–ด๊ฐ€ ์•„๋‹Œ ์ฝ”์–ด!)๋ฅผ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋ฐฉ์‹(FP or OOP)์œผ๋กœ ๊ตฌ์„ฑํ•˜๊ณ  Flux์ฒ˜๋Ÿผ ๋‹จ๋ฐฉํ–ฅ ํ๋ฆ„์œผ๋กœ ์—ฎ์–ด๋‚ด๋Š” ๋‹ˆ์ฆˆ์— ๋งž์ถฐ์ง„ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

๐Ÿค– usesotre-ts ์„ค์น˜ ๋ฐ ์„ค์ •

usesotre-ts ์„ค์น˜

npm install usestore-ts

Typescript @ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  tsconfig.json ํŒŒ์ผ ์†์„ฑ ์ถ”๊ฐ€

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

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‹ค์Šต

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

Store ์ƒ์„ฑ

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

// CounterStore.ts

import { singleton } from 'tsyringe';

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

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

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

Custom Hook ์ž‘์„ฑ

usestore-ts๊ฐ€ ์ œ๊ณตํ•˜๋Š” useStore ํ›…์œผ๋กœ ๊ธฐ์กด useObjectStore๋ฅผ ๋Œ€์ฒด forceUpdate ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋จธ๊ธˆ๊ณ  ์žˆ๋‹ค.

// useCounterStore.ts

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);
}

const [ state , store ] = useStore(counterStore) ๋ฐ˜ํ™˜๊ฐ’ ์‚ฌ์šฉํ•˜๊ธฐ

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

export default function Counter() {
  const [{ count }] = useCounterStore();  // ์ƒํƒœ๊ฐ’๋งŒ ์‚ฌ์šฉ

  return (
    <div>
      <p>{`count: ${count}`}</p>
    </div>
  );
}
// CounterControl.tsx

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

export default function CounterController() {
  const [, store] = useCounterStore(); // ์Šคํ† ์–ด์˜ Action๋งŒ ์‚ฌ์šฉ

  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>
  );
}

โš ๏ธ ์‚ฌ์šฉ์‹œ ์ฃผ์˜ ์‚ฌํ•ญ

๋น„๋™๊ธฐ ํ•จ์ˆ˜์— @Action์„ ๋ถ™์ด๋ฉด ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ์˜! ๋ณ„๋„์˜ ์•ก์…˜์„ ๋งŒ๋“ค๋ฉด ์‹ ๊ฒฝ ์“ธ ๋ถ€๋ถ„์ด ์ค„์–ด๋“ ๋‹ค.

@singleton()
@Store()
class PostStore {
  posts: Post[] = [];
  
  //@Action() ๐Ÿ‘ˆ๐Ÿป ์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ๋‹ค?  
  async fetchPosts() {
    this.startLoading();
  
    const posts = await fetchPosts();

    this.completeLoading(posts);
  }
  
  @Action()
  startLoading() {
    this.posts = [];
  }
  
  @Action()
  completeLoading(posts: Post[]) {
    this.posts = posts;
  }
}

๐Ÿ”— ์ฐธ๊ณ 

Last updated