Electron & React & Redux & TypeScript 앱 제작 워크샵을 시도했습니다.

htps : // 이 m / y_ hr / ms / 5c18d d1621b5342 A05 계속.

개요



다음을 시도한 기록. 좋은 기사에 감사.

  • htps : // 코 m/새우 하라_켄지/있어 ms/25에 59f7132b96cb886f3 (이전 완료)

  • htps : // 코 m / 새우 하라 _ 켄지 / ms / 6 1c3d6d16cf07b60 (이전 완료)

  • htps : // 코 m / 새우 하라_ 켄지 / ms / 1 아 043794014dc2f3 아 7db (도중까지 전회 완료)

  • 환경



    Node.js 및 npm 버전
    $ node -v
    v10.13.0
    $ npm -v
    6.4.1
    

    component 만들기



    사용자 이름 입력 화면 만들기



    ts/components/UserForm.tsx
    import React from 'react';
    import IUser from '../states/IUser';
    import { TextBox } from './TextBox';
    
    /**
     * ユーザ名を入力して表示する
     */
    class UserForm extends React.Component<IUser, {}>{
        public render() {
            return (
                <div>
                    <p>
                        <TextBox label="ユーザー名" type="text" value={this.props.name}
                            onChangeText={this.onChangeText} />
                    </p>
                    <p>名前: {this.props.name}</p>
                </div>
            );
        }
    
        private onChangeText = (value: string) => {
            // action や store ができてから書く
        }
    }
    
    

    action 및 action creator 만들기



    uuid 설치
    $ npm install --save uuid && npm install --save-dev @types/uuid
    

    ts/actions/UserNameEvents.ts
    import Redux from 'redux';
    import { v4 as UUID } from 'uuid';
    
    /**
     * ユーザー名を変更するアクション・タイプ
     */
    export const CHANGE_USER_NAME = UUID();
    
    /**
     * ユーザー名を変更するアクション
     */
    export interface IChangeUserNameAction extends Redux.Action {
        /** 変更する名前の文字列 */
        name: string;
    }
    
    /**
     * ユーザー名変更アクション・クリエイター
     * @param name 変更する名前の文字列
     * @return ユーザー名変更アクション
     */
    export const createChangeUserNameAction: Redux.ActionCreator<IChangeUserNameAction> = (name: string) => {
        return {
            name,
            type: CHANGE_USER_NAME,
        };
    };
    
    

    reducer 만들기



    clone 설치
    npm install --save clone && npm install --save-dev @types/clone
    

    ts/reducers/UserReducer.ts
    import Clone from 'clone';
    import Redux from 'redux';
    
    import { CHANGE_USER_NAME, IChangeUserNameAction } from '../actions/UserNameEvents';
    import IUser, { initUser } from '../states/IUser';
    
    export const UserReducer: Redux.Reducer<IUser> = (childState = initUser, action) => {
        let newChildState: IUser = childState;
        switch (action.type) {
            case CHANGE_USER_NAME:
                {
                    newChildState = Clone(childState);
                    newChildState.name = (action as IChangeUserNameAction).name;
                }
                break;
        }
        return newChildState;
    };
    
    

    스토어 만들기



    ts/Store.ts
    import { combineReducers, createStore } from 'redux';
    import { UserReducer } from './reducers/UserReducer';
    import IUser from './states/IUser';
    
    /**
     * store のデータ型を定義する。(親state)
     * 
     * プロパティには、管理する child_state を指定する
     */
    export interface IState {
        User: IUser;
        // state が増えたら足していく
    }
    
    // 複数の reducer を束ねる
    const combinedReducers = combineReducers<IState>({
        User: UserReducer,
        // reducer が増えたら足していく
    });
    
    // グローバルオブジェクトとして、store を作成する。
    export const store = createStore(combinedReducers);
    
    // improt store from './Store' とアクセスできるように default として定義する
    export default store;
    
    

    store와 component를 연결



    ts/components/UserForm.tsx
    diff --git a/ts/components/UserForm.tsx b/ts/components/UserForm.tsx
    index 36a22f1..6c3f614 100644
    --- a/ts/components/UserForm.tsx
    +++ b/ts/components/UserForm.tsx
    @@ -1,5 +1,7 @@
     import React from 'react';
    +import { connect, MapStateToPropsParam } from 'react-redux'; // 追加
     import IUser from '../states/IUser';
    +import { IState } from '../Store'; // 追加
     import { TextBox } from './TextBox';
    
     /**
    @@ -22,3 +24,9 @@ class UserForm extends React.Component<IUser, {}>{
             // action や store ができてから書く
         }
     }
    +// 追加 -->
    +const mapStateToProps = (state: IState) => {
    +    return state.User;
    +};
    +export default connect(mapStateToProps)(UserForm);
    +// <- 追加
    

    component에서 action을 reducer로 보내기



    ts/components/UserForm.tsx
    diff --git a/ts/components/UserForm.tsx b/ts/components/UserForm.tsx
    index 6c3f614..a51d8f8 100644
    --- a/ts/components/UserForm.tsx
    +++ b/ts/components/UserForm.tsx
    @@ -1,7 +1,8 @@
     import React from 'react';
     import { connect, MapStateToPropsParam } from 'react-redux'; // 追加
     import IUser from '../states/IUser';
    -import { IState } from '../Store'; // 追加
    +import { createChangeUserNameAction } from '../actions/UserNameEvents'; // 追加
    +import store, { IState } from '../Store'; // 変更
     import { TextBox } from './TextBox';
    
     /**
    @@ -21,7 +22,7 @@ class UserForm extends React.Component<IUser, {}>{
         }
    
         private onChangeText = (value: string) => {
    -        // action や store ができてから書く
    +        store.dispatch(createChangeUserNameAction(value));
         }
     }
     // 追加 -->
    

    HTML로 렌더링



    ts/index.tsx
    diff --git a/ts/index.tsx b/ts/index.tsx
    index c25e4e5..58d6af1 100644
    --- a/ts/index.tsx
    +++ b/ts/index.tsx
    @@ -1,9 +1,15 @@
     import React from 'react';
     import ReactDom from 'react-dom';
    +import { Provider } from 'react-redux'; // 追加
    +import UserForm from './components/UserForm'; // 追加
    +import Store from './Store'; // 追加
    
     const container = document.getElementById('contents');
    -
    +// 変更 -->
     ReactDom.render(
    -    <p>こんにちは、世界</p>,
    +    <Provider store={Store}>
    +        <UserForm />
    +    </Provider>,
         container,
     );
    +// 変更 <--
    

    빌드하고 동작 확인한다.



    webpack 실행 및 electron 시작
    $ npm run build
    $ npm start
    

    움직였다!



    자산 구성



    감상


  • 제대로 움직여 감동했다
  • Redux에 익숙해지기
  • 클래스나 정수의 import가 종횡무진으로 쫓아내지 않게 된다. 뇌내 맵이 필요.
  • 라이브러리에 추가한 uuid 이나 clone 는 일반적인 모범 사례일까?
  • component등의 UI관련 클래스와, action등의 Redux관련 클래스는, 좀 더 폴더등을 정리해, 관심을 분리할 수 없는 것일까? 이런 것일까.
  • VSCode로 소스를 성형해도 tslint에 경고하지 않으려고합니다.

  • 이상

    좋은 웹페이지 즐겨찾기