React-Redux이지만 Reducer도 Action도 쓰지 않고 Dispatch조차 사용하지 않고 데이터도 왠지 받을 수 있도록 하는 방법

React-Redux이지만 Reducer도 Action도 쓰지 않고 Dispatch조차 사용하지 않고 데이터도 왠지 받을 수 있도록 하는 방법



지난번
Redux가 너무 귀찮기 때문에 모든 것을 숨기면서 그 힘을 끌어내기로 결정했습니다.

어쨌든 귀찮은 Flux



React상에서의 상태 관리는, 일과 같이 Flux의 생각을 이용해 만들어지고 있습니다.

Action의 커멘드를 정의해 Dispatch로 송신해, Reducer로 처리해 Store에 기입해, View가 Store의 갱신을 인지해 처리를 실시한다고 하는 흐름입니다. 이러한 처리의 귀찮은 점은, 모두가 전부, 기술 개소가 흩어져 버린다는 것입니다.

어쨌든 아무것도 귀찮아서, 이 지옥에서 빠져나가는 방법을 찾았습니다. 결과적으로 위에서 쓴 것과 같은 것을 쓰지 않고 쉽게 Store 데이터를 조작하는 방법에 도착했습니다.

환경설정과 필요한 패키지



이 샘플 프로그램을 실행하려면 React+TypeScript 환경을 준비하십시오.
또한 다음 패키지를 설치해야 합니다.
npm -D i @jswf/redux-module

샘플 프로그램



훅스의 Function 컴포넌트와 Class 컴포넌트에서의 이용법을 동시에 싣고 있으므로, 프로그램이 조금 길어지고 있습니다.
안에서 하고 있는 것은 input의 내용을 컴퍼넌트간에 공유한다고 하는 것입니다.
만약 이것을 하기 위해서만 Redux의 서식을 진지하게 쓰면, 확실히 낭비 지옥에 떨어질 수 있을 것입니다.

컴포넌트 간의 데이터 공유에는 ReduxModule이라는 클래스를 상속하여 이용합니다.
클래스를 만들면 클래스마다 하나의 Store 영역이 할당됩니다.
따라서 동일한 클래스를 사용하는 한 동일한 데이터를 참조 할 수 있습니다.
또, 읽고 쓰기의 접수도 모두 이 ReduxModule 상속 클래스가 담당하므로, 처리를 여기저기 쓸 필요는 없습니다



htps : // 기주 b. 코 m / 그럼 Sc 리 pt 우드 wF 라메를 rk / 레즈 x - 모즈 ぇ mp ぇ

index.tsx
import React, { Component } from "react";
import * as ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import {
  ModuleReducer,
  useModule,
  ReduxModule,
  mapModule,
  mapConnect
} from "@jswf/redux-module";

/**
 *データ構造の定義(TypeScript使用時)
 *
 * @export
 * @interface TestState
 */
export interface TestState {
  msg: string;
}
/**
 *Storeアクセス用クラス
 *(クラスごとに自動的にStoreに領域を確保する)
 * @export
 * @class TestModule
 * @extends {ReduxModule<TestState>}
 */
export class TestModule extends ReduxModule<TestState> {
  //ここに初期値を設定可能
  protected static defaultState: TestState = {
    msg: "初期値"
  };
  //以下のようなアクセス用のメソッドは、必ずしも作る必要は無い
  //getStateとsetStateはpublicなので、外から直接書き換えてしまってもOK
  public getMessage() {
    return this.getState("msg")!;
  }
  public setMessage(msg: string) {
    this.setState({ msg });
  }
}

/**
 *Hooks用サンプル
 *
 * @returns
 */
function HooksApp() {
  //モジュールのインスタンスを受け取る
  //useModuleの使用可能場所の制限は他のhookと同じ
  const testModule = useModule(TestModule);
  //以下のようにPrefixを付けると、同じクラスが違う領域を持つことも出来る
  //const testModule = useModule(TestModule,"Prefix");
  return (
    <>
      <div>FunctionComponent</div>
      <input
        value={testModule.getMessage()}
        onChange={e => testModule.setMessage(e.target.value)}
      />
      <hr />
    </>
  );
}

/**
 *Class用サンプル
 *
 * @class _ClassApp
 * @extends {Component}
 */
class _ClassApp extends Component {
  render() {
    //モジュールのインスタンスを受け取る
    //Hooksと名前と引数が微妙に違うので注意
    const testModule = mapModule(this.props, TestModule);
    return (
      <>
        <div>ClassComponent</div>
        <input
          value={testModule.getMessage()}
          onChange={e => testModule.setMessage(e.target.value)}
        />
        <hr />
      </>
    );
  }
}
//クラスコンポーネントを利用する場合は以下の方法でマッピングする
//ここで宣言したモジュール以外はクラスで使用できない
//モジュールは配列で複数指定も可能
const ClassApp = mapConnect(_ClassApp, TestModule);

//Reduxに専用のReducerを関連付ける
//他のReducerと併用することも可能
const store = createStore(ModuleReducer);
ReactDOM.render(
  <Provider store={store}>
    <HooksApp />
    <ClassApp />
  </Provider>,
  document.getElementById("root") as HTMLElement
);

필요한 것의 정리



1 ModuleReducer를 Redux의 Store와 연결
2 ReduxModule을 상속하는 데이터 클래스 만들기
3 Class 컴퍼넌트를 사용하는 경우는 mapConnect 로 사용하는 데이터 클래스를 관련짓는다
4 useModule/mapModule에서 데이터 클래스 호출
5 setState/getState로 데이터 읽기/쓰기

일단 해설해 두는 부가 기능



사족이 되기 때문에 최소한으로 유지합니다만, 데이터 클래스는 외부 참조 기능도 붙어 있습니다.
다른 데이터 클래스의 기능이 필요한 경우는 includes에 이용하는 모듈을 지정해 두면, getModule로 대상의 클래스를 호출할 수가 있습니다.
export class OtherModule extends ReduxModule {
  static includes = [TestModule]
  public getMessage() {
    return this.getModule(TestModule).getState("msg")!;
  }
  public setMessage(msg: string) {
    this.getModule(TestModule).setState({ msg });
  }
}

요약



어쨌든 상태 관리가 쉬워졌습니다. 이것을 사용하는 것에 의해, 컴퍼넌트간의 수속의 대부분이 생략 가능하게 됩니다. 컴포넌트 간의 데이터 공유에 Redux를 사용하고 싶지만, Flux적인 쓰기가 싫다고 생각한다면 꼭 사용해 보세요.

좋은 웹페이지 즐겨찾기