2
2

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 Reduxを簡単に利用してみる

Last updated at Posted at 2018-10-18

前回のコードにAPI照会機能を追加したいと思います。
非同期処理の記述はsagaと悩みましたが、ひとまずthunkを利用しました(既存コードの理解も考慮)。また通信にはaxiosを利用します。

準備

axiosとthunkをインストールします。

npm install --save axios
npm install --save redux-thunk

実装

Thunkを利用するためのactions, reducer関連の記述を追加します。

actions

通信処理用の3つのaction(creater)を定義します。

  • 開始時:FETCH_MESSAGES(requestMessages)
  • 成功時:FETCH_MESSAGES_SUCCESS(recieveMessages)
  • 失敗時:FETCH_MESSAGES_ERROR(recieveMessages)

それと、それらを実際にコールするfetchMessages()を定義します。

reducers

新規にデータ処理関連を取り扱うreducerを定義し、combineReducers()します。

middlewareの追加

最後にというわけではないですが、middleware利用の定義をcreateStore()に追加します。

redux.js
import {combineReducers, createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk'
import axios from 'axios'

//actions.js
//user関連
export const editName = _name => ({
    type: "EDIT_NAME",
    name: _name
});

export const deleteName = () => ({
    type: "DELETE_NAME",
    name: ''
});

//api連携関連
export const requestMessages = () => ({
    type: "FETCH_MESSAGES"
});

export const recieveMessages = json => ({
    type: "FETCH_MESSAGES_SUCCESS",
    data: json
});

export const errorMessages = () => ({
    type: "FETCH_MESSAGES_ERROR",
});

//リクエストの本体(この中で上記action createrを使う)
export const fetchMessages = () => (
    dispatch => {
        //start
        dispatch(requestMessages());
        return axios.get('http://localhost/').then((res)=>{
            //end
            dispatch(recieveMessages(res.data));
        }).catch((error) => {
            dispatch(errorMessages());
        });
    }
)

//reducers.js
//reducerの_userと命名
export const _user = (state = {}, action) => {
    switch (action.type){
        case 'EDIT_NAME':
            return action.name;
        case 'DELETE_NAME':
            return action.name;
        default:
            return state;
    }
}

//reducers(data関連)
export const _data = (state = {}, action) => {
    switch(action.type){
        case 'FETCH_MESSAGES':
            return Object.assign({}, state, {
                isFetching: true
            });
        case 'FETCH_MESSAGES_SUCCESS':
            return Object.assign({}, state, {
                isFetching: false,
                data: action.data
            });
        case 'FETCH_MESSAGES_ERROR':
            return Object.assign({}, state, {
                isFetching: false,
                message: 'error'
            });
        default:
            return state;
    }
}

//keyを指定して別名に(keyを指定しないと_userとなる) state.userで参照できる。
export const reducers = combineReducers({
    user: _user,
    data: _data
});

//値は以下の構造となる。
const initialState = {
    user: {
        name: 'foo'
    },
    data: {
        data: {
            status: 'N/A',
            data: []
        }
    }
};

//store.js
export const store = createStore(reducers,initialState, applyMiddleware(thunkMiddleware));

App.jsを記述します。データを表示するための<DataList/>を追加しました。なお、<DataList>の実装は別途DataList.jsを定義して行います。

App.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { editName, deleteName, fetchMessages } from './redux'
import DataList from './DataList'


class App extends Component {
  render() {
    return (
      <div className="App">
        {/* USER.name等で参照可 */}
        <h3>{this.props.USER.name}</h3>
        <button onClick={() => this.props.editName({name: 'my name is hoge.'})}>Add</button>
        <button onClick={() => this.props.deleteName()}>Del</button>
        <button onClick={() => this.props.fetchMessages()}>Fetch</button>
        <h3>{this.props.DATA.data.status}</h3>
        {/* <DataList {...props}/> */}
        <DataList/>
      </div>
    );
  }
}

//combineで付けたkey名でマッピング(props.USERにマップ)
const mapStateToProps = state => ({
  USER: state.user,
  DATA: state.data
});

//dispatchはそのまま
//props.addName()にマップ
const mapDispatchToProps = {
  editName,deleteName,fetchMessages
}

//バインドさえれたAppが返る
export default connect(mapStateToProps,mapDispatchToProps)(App)
// export default App;

index.jsに変更はありません(Providerで囲ってstoreを指定してるだけ)。

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';


import { Provider } from 'react-redux'
import { store } from './redux'

ReactDOM.render(
    <Provider store={store}>
        <App/>
    </Provider>,
    document.getElementById('root')
);

DataList.jsファイルを用意し記述します。
storeにconnectし、利用できるようにしています。

import React, { Component } from 'react';
import { connect } from 'react-redux'
// import { editName, deleteName, fetchMessages } from './redux'



class DataList extends Component {
    render() {

        const items = this.props.DATA.data.data.map(item => {
            return (
                <li key={item.id}>{item.id} {item.name} {item.age}</li>
            );
        });
        return (
            <ul>
                {items}
            </ul>
        );
    }
}

//combineで付けたkey名でマッピング(props.USERにマップ)
const mapStateToProps = state => ({
    DATA: state.data
});

//dispatchはそのまま
//props.addName()にマップ
const mapDispatchToProps = {
}

//バインドさえれたAppが返る
export default connect(mapStateToProps, mapDispatchToProps)(DataList)

API側のソース。

<?php

    $res['status'] = 'OK';
    $res['data'] = [
            ["id"=>1,"name"=>"yamada","age"=>33],
            ["id"=>2,"name"=>"tanaka","age"=>44],
            ["id"=>3,"name"=>"suzuki","age"=>55]
        ];

    header('Access-Control-Allow-Origin:*');
    echo json_encode($res);
2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?