3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[React.js]TypeScriptでRedux-zeroを使ってみる

Last updated at Posted at 2018-01-20

Reducerが面倒なので、軽量なreduxのライブラリ「redux-zero」を使ってみようと思います。

1.ベースを作る

TypeScriptが好きなので、下記記事をもとにReact + Redux + TypeScriptのベースを作ります。
https://qiita.com/uryyyyyyy/items/3ad88cf9ca9393335f8c

2.redux-zeroをinstallする。

npm install --save redux-zero

3.storeを修正する。

store.tsを修正します。

store.ts
import * as createStore from "redux-zero"

interface IAppState {
  count: number;
  users: any[] // 必要な場合はuserのinterfaceを作る
}

const initialState: IAppState = {
  count: 1,
  users: []
};

// 「型に呼び出しシグネチャがない式を呼び出すことはできません。」というエラーが起きるので、一度any型の変数に格納
const _createStore: any = createStore;
const store = _createStore(initialState);

export default store;

4.actionを作成する。

Reducerがなくなるので、module.tsをactions.tsとし、actionを作成します。
非同期処理(getUsers)では、HTTP clientにはaxiosを利用し、Random User Generatorよりダミーのユーザーデータを取得しています。

actions.ts
import axios from 'axios';

const actions = ({ setState }: any) => ({
  // async sample
  getUsers: (state: any) => {
    return axios.get(`https://randomuser.me/api/?results=5`)
      .then(payload => ({ users: payload.data.results }))
      .catch(error => ({ error, loading: false }))
  },
  // increment
  increment: (state: any, payload: any) => {
    return { count: state.count + payload };
  },
  // decrement
  decrement: (state: any, payload: any) => {
    return { count: state.count - payload };
  }
});

export default actions;

5.Componentを修正する。

Counter.tsxを修正します。
初期表示時と、ボタンを押したときにそれぞれactionを呼ぶようにします。
今回はContainer.tsxは不要なので削除します。

Counter.tsx
import * as React from "react";
import { Connect } from "redux-zero/react";
import { getActions  }  from 'redux-zero/svelte';

import actions from "./actions";

const mapToProps = ({ count }: any) => ({ count });

interface Props {
  store: any;
}
interface State {}

/**
 * 
 * 
 * @export
 * @class Counter
 * @extends {React.Component}
 */
export default class Counter extends React.Component<Props, State> {
  actions: any;

  constructor(props: Props) {
    super(props);
    // set actions
    this.actions = getActions(props.store, actions);
  }

  componentDidMount(): void {
    this.actions.getUsers();
  }

  render(): JSX.Element {
    return (
      <Connect mapToProps={mapToProps}>
        {({ count, users }: any) => 
          <div>
            <div>
              <p>score: {count}</p>
              <button onClick={e=>this.actions.increment(10)}>increment</button>
              <button onClick={e=>this.actions.decrement(1)}>decrement</button>
            </div>
            <div>
              <ul>
                { users.map((user: any, idx: number) => {
                  return <li key={idx}>{user.email}</li>
                }) }
              </ul>
            </div>
          </div>
        }
      </Connect>
    )
  }
};

6.Index.tsxを修正する。

Counterコンポーネントにstoreを渡すようにします。

Index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import store from './store'

import Counter from './counter/Container'
import { render } from "react-dom";
import { Provider }  from "redux-zero/react";

const App = () => (
  <Provider store={store}>
    <Counter store={store} />
  </Provider>
);

render(<App />, document.getElementById("app"));

以上です。
フォルダは以下のような構成になっていると思います。

.
├── index.html
├── package.json
├── src
│   ├── counter
│   │   ├── actions.ts
│   │   └── Counter.tsx
│   ├── Index.tsx
│   └── store.ts
├── tsconfig.json
└── webpack.config.dev.js

以下のような画面が表示されます。
incremetボタンとdecrementボタンを押下してscoreが増減していれば実装完了です。

React_minimal.png
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?