DeRxJSViewModel 모드: 상태 관리의 E=mc^2 [제2부분]

👋 안녕하세요. 이 글은 DERxJS 모델의 목표를 설명하는 글의 연장선상입니다.
  • 상태 관리 코드와 표시 코드를 완전히 분리
  • RxJS의 장점을 극대화하고 부정적인 영향을 최소화
  • 다음 단계 테스트 [그리고 우리의 모든 상태 관리 코드를 AI에 인계할 가능성]
  • 그 글에서 우리는 대부분의 힘든 일을 했다. 즉, 우리의 상태 관리 코드를 개발하고, '시간선 테스트' ('어떤' 상태가 어떤 모양인지 단언할 수 있을 뿐만 아니라, '언제' 상태가 어떤 모양인지 단언할 수 있도록 허용) 를 통해 모든 변두리 사례를 전면적으로 테스트했다.
    이 문서에서는 상태 관리 코드를 설명하고 React, Angular, Vanilla JS 등 3개의 프런트엔드 '프레임워크'에서 사용하는 방법을 보여 드리겠습니다.

    리액션


    DeRxJS의 목표 중 하나는 우리의 코드 라이브러리에서 실제 RxJS 코드를 삭제하는 것이다.이전 예에서 우리는 @derxjs/reducer 어떻게 우리가 상태 관리를 작성하고 RxJS를 이용하는 데 도움을 줄 수 있는지 토론했지만 실제로는 어떤 RxJS 코드도 직접 작성할 필요가 없었다.

    본고에서, 나는 매우 흥분해서 소개했다. @derxjs/react. 이것은 우리가react 프레젠테이션 코드에서 같은 방법을 이용할 수 있게 할 것이다.
    솔직히 말하면, 나는 React를derxjs의 첫 번째 프레젠테이션 원고를 기반으로 하는 소프트웨어 패키지로 열거했는데, 이것은 어느 정도에 React가 인기가 있기 때문이다.그러나 그 외에 내가 먼저 겨냥한 두 가지 큰 이유가 있다.
  • RxJS랑 리액트랑 같이 잘 못 놀아요 [지금!]
  • React에 대해 내가 가장 좋아하는 것은 상태 관리를 제외하고 React의 거의 모든 내용이 특정 영역이 아니라는 것이다!(흥미로운 것은 이것은 거의 완전히 Angular와 상반된다고 생각한다. 나는 Angular가 특정한 지역에 있다고 생각하지만 상태 관리는 제외)React와 RxJS의 결합은 이 차이를 줄일 수 있기 때문에 당신이 작성한 상태 관리 코드는 React 코드의 다른 부분과 마찬가지로 역은 알 수 없다.
  • 전반적으로 말하면, 나는 이미 오랫동안 반응하지 않았다.나의 동기는 거의 완전히 이기적이었다. 만약 이 소프트웨어 패키지가 내가 원하는 방식으로 일한다면, 이것은 내가 전방 개발을 진행하는 이상적인 환경이 될 것이라고 나는 생각한다.
    다음은 @derxjs/react 코드의 일반api입니다.
    export const TicTacToe = () => {
      return DeRxJSComponent<
        TicTacToeViewModelInputs,
        TicTacToeViewModel,
        TicTacToeProps
      >({
        viewModel$: ticTacToeViewModel$,
        component: TicTacToeView as any,
        initialValue: createInitialViewModel(),
        triggerMap: {
          spaceClick: 'userSpaceClickEvents$',
          resetClick: 'userResetClickEvents$',
        },
        inputs: {
          ai: randomAi,
        },
      });
    };
    
  • viewModel$는 이전 문장
  • 에서 우리 작품에서 도입한 것이다
  • component는 표현 성분이다(우리는 아래에서 볼 것이다!)
  • initialValue 우리 상태의 시작값createInitialViewModel() 함수도 이전 글에서 왔다)
  • triggerMap는 [유형 안전!]대상, 이 대상은 구성 요소의 '트리거' 함수의 이름을 viewModel$ 관찰할 수 있는 입력에 비추는 것입니다.트리거 함수는 프레젠테이션 구성 요소를 전달하는 데 필요한 정보를 @derxjs/react 패키지에 전달하여 관찰할 수 있도록 하는 방법입니다. (따라서 RxJS 코드를 직접 작성할 필요가 없습니다.)
  • inputs는 우리가 viewModel$ 기능에 어떠한 비반응(또는 관찰할 수 없는) 입력을 제공하는 방식이다.주의, 우리는 여기서 randomAi 함수를 전달한다. 기본적으로 이런 방식으로 매개 변수화viewModel$의 기능을 한다.(미래의 업무에서'비길 데 없는'인공지능을 창조하는 것도 재미있을 것이다!)
  • 이 API는 모든 표현 코드를 "표시"구성 요소로 작성하고 @derxjs/view 모델에 모든 지능을 위임하며, 제공된 트리거 함수를 사용하여 메시지를 전달할 수 있도록 합니다.
    다음은 코드의 최종 모양입니다.
    interface TicTacToeProps {
      spaceClick: (spaceCoordinates: SpaceCoordinates) => void;
      resetClick: () => void;
    }
    
    interface SpaceProps {
      contents: SpaceContent;
      spaceCoordinates: SpaceCoordinates;
      clickHandler: (spaceCoordinates: SpaceCoordinates) => void;
    }
    const Space = ({ contents, clickHandler, spaceCoordinates }: SpaceProps) => (
      <div>
        <button onClick={() => clickHandler(spaceCoordinates)}>
          {contents.toUpperCase()}
        </button>
      </div>
    );
    
    function TicTacToeView({
      state,
      triggers,
    }: {
      state: TicTacToeViewModel;
      triggers: TicTacToeProps;
    }) {
      return (
        <>
          <h2>{state.turn}</h2>
          <div className={'border'}>
            <div className={'board'}>
              {([0, 1, 2] as const)
                .map((row) => ([0, 1, 2] as const).map((column) => [row, column]))
                .flat()
                .map(([row, column]) => (
                  <Space
                    contents={state.board[row][column]}
                    spaceCoordinates={{ row, column }}
                    clickHandler={triggers.spaceClick}
                    key={`${row}:${column}`}
                  />
                ))}
            </div>
          </div>
          <button className="reset" onClick={triggers.resetClick}>
            Reset
          </button>
        </>
      );
    }
    
    onClick가 우리가 정의한'촉발 함수'로 어떻게 설정되었는지 주의하십시오.
    다음은 실행 중인 코드입니다.

    모서리의


    다음: 각도!앞에서 말한 바와 같이, 나는 Angular가 국가 관리 방면에서 통상적으로 매우 영역에서 알 수 없다고 생각한다.특히 RxJS에는 매우 우호적이다.
    그래서 @derxjs/angular 패키지가 정말 필요한지 모르겠습니다.최종적으로, 우리는 우리가 작성할 더 많은 RxJS 코드를 숨길 수 있는 유틸리티 패키지를 만들 수 있지만, 나는 아직 이 방면의 계획이 없다.
    다음은 우리가 작성할 Typescript 구성 요소 코드입니다.
    export class AppComponent {
      userResetClickObserver!: Observer<void>;
      userResetClickEvents$ = new Observable<void>(
        (observer) => (this.userResetClickObserver = observer)
      );
      userSpaceClickObserver!: Observer<SpaceCoordinates>;
      userSpaceClickEvents$ = new Observable<SpaceCoordinates>(
        (observer) => (this.userSpaceClickObserver = observer)
      );
      vm$ = ticTacToeViewModel$({
        ai: randomAi,
        userSpaceClickEvents$: this.userSpaceClickEvents$,
        userResetClickEvents$: this.userResetClickEvents$,
      });
      rows: BoardIndex[] = [0, 1, 2];
    
      handleSpaceClick(coordinates: SpaceCoordinates) {
        this.userSpaceClickObserver.next(coordinates);
      }
    
      handleResetClick() {
        this.userResetClickObserver.next();
      }
    }
    
    '구성시' 클래스에'observer '속성을 만들어서 관찰 대상을 만드는 방법을 주의하십시오. 그리고 클릭 핸들러 방법에서 이 관찰 대상을 호출합니다. next()(이것은 우리의 React 코드와 본질적으로 같은'메시지 전달'이지만 @derxjs/React 패키지는 대부분의 실제 코드를 숨깁니다)
    "React 예시와 유사하게 템플릿에서""구현""구성 요소를 볼 수 있습니다. 유일한 예외는 우리viewModel$를 템플릿 맨 위에 전달하는 각도의 비동기 파이프라인입니다.
    <h1>Tic Tac Toe</h1>
    <ng-container *ngIf="vm$ | async as vm">
      <h2>{{ vm.turn }}</h2>
      <div class="border">
        <div class="board">
          <ng-container *ngFor="let row of rows">
            <div *ngFor="let column of rows">
              <button (click)="handleSpaceClick({ row, column })">
                {{ vm.board[row][column] | uppercase }}
              </button>
            </div>
          </ng-container>
        </div>
      </div>
      <button class="reset" (click)="handleResetClick()">Reset</button>
    </ng-container>
    
    좋기도 하고 간단하기도 하다.다음은 각도 코드의 Stackblitz입니다.

    바닐라 JS


    이 예에서 우리는 dom-manipulation API를 사용하여 예시의 반작용력과 각도 향상을 집행할 것이다.다음은 우리가 작업한 간소화 버전이다.
  • 텍스트를 클릭하거나 업데이트할 수 있도록 구성 요소에 '템플릿' 을 만듭니다.이 예는 약간 운이 좋다. 왜냐하면 DOM의 모든 요소는 정적 (추가하거나 삭제할 필요가 없기 때문에, 우리는 DOM의 Element 대상을 변하지 않고 텍스트 내용을 변경할 수 있다.만약 그렇지 않다면 이것은 매우 어려울 것이다.
  • RxJS의 fromEvent 를 사용하여 단추의'클릭'이벤트의 관찰성을 얻습니다.
  • 관찰할 수 있는 대상이 생기면 React and Angular에서 사용하는 함수viewModel$에 전달하여 관찰할 수 있는 보기 모델을 만든다.
  • 이 관찰 대상을 구독하고 버튼의 텍스트 내용을 변경하여'board'를 업데이트하여 보기 모델 대상의 board 속성과 일치하도록 합니다.
  • 다음은 Stackblitz의 상황입니다.

    결론


    이것은 총결산이다!!이 글이 멋진 생각을 불러일으키길 바란다.만약 상태 관리나 양호한 코드 체계 구조를 알고 싶다면 반드시 연락하거나 보십시오the DeRxJS repo!

    작성자 정보



    Zack DeRose[또는DeRxJS, 당신이 좋아한다면]:
  • a GDE in Angular
  • 최근 nx conf/NgConf/RxJS Live/The Angular Show/ZDS 스피커
  • 의 작성자@derxjs OSS packages
  • 선임 엔지니어 및 엔지니어링 관리자Nrwl
  • 나의 personal website를 보고 나의 개발 내용을 더 알아보세요!만약 당신이 나를 고용하여 당신의 코드 라이브러리를 돕거나 당신의 팀의 Nx/NgRx/DeRxJS/RxJS/State 관리 수준을 향상시키는 데 도움을 주고 싶다면 bug/로 가세요!(저는 훌륭한 것을 구축하는 것을 특히 좋아합니다. 그리고 공부를 갈망하는 똑똑한 개발자와 팀을 구성하는 것을 좋아합니다.)

    좋은 웹페이지 즐겨찾기