2016-11-29 62 views
0

我的代碼如下:如何使Redux的外部API調用反應

const LOAD = 'redux-example/LOAD'; 
const LOAD_SUCCESS = 'redux-example/LOAD_SUCCESS'; 
const LOAD_FAIL = 'redux-example/LOAD_FAIL'; 
import axios from 'axios'; 
const initialState = { 
    loaded: false 
}; 
export default function info(state = initialState, action = {}) { 
    switch (action.type) { 

    case LOAD: 
    return { 
    ...state, 
    loading: true 
    }; 
    case LOAD_SUCCESS: 
    return { 
    ...state, 
    loading: false, 
    loaded: true, 
    data: action.result 
    }; 
case LOAD_FAIL: 
    return { 
    ...state, 
    loading: false, 
    loaded: false, 
    error: action.error 
    }; 
default: 
    return state; 
} 
} 
export function load() { 
    return { 
     types: [LOAD, LOAD_SUCCESS, LOAD_FAIL], 
     promise: (client) => client.get('http://example.com/getdata') 
    }; 
} 

我使用https://github.com/erikras/react-redux-universal-hot-example例如作爲入門套件。我希望基於api調用example.com/api.But,但我無法通過異步調用來實現。我在中間件中遇到錯誤,無法讀取未定義的promise。我的中間件代碼如下所示。

export default function clientMiddleware(client) { 
return ({dispatch, getState}) => { 
return next => action => { 
    if (typeof action === 'function') { 
     return action(dispatch, getState); 
    } 
    const { promise, types, ...rest } = action; // eslint-disable-line no-redeclare 
    if (!promise) { 
     return next(action); 
    } 
    const [REQUEST,SUCCESS,FAILURE] = types; 
    next({...rest, type: REQUEST}); 
    const actionPromise = promise(client); 
    actionPromise.then(  
     (result) => next({...rest, result, type: SUCCESS}), 
     (error) => next({...rest, error, type: FAILURE}) 
    ).catch((error)=> { 
     console.error('MIDDLEWARE ERROR:', error); 
     next({...rest, error, type: FAILURE}); 
    }); 
    return actionPromise; 
}; 
}; 
} 

MY分量代碼是如下

import React, {Component, PropTypes} from 'react'; 
import {bindActionCreators} from 'redux'; 
import {connect} from 'react-redux'; 
import {load} from 'redux/modules/info'; 

@connect(state => ({info: state.info.data}),dispatch =>  bindActionCreators({load}, dispatch)) 

export default class InfoBar extends Component { 
static propTypes = { 
info: PropTypes.object, 
load: PropTypes.func.isRequired 
} 
render() { 
const {info, load} = this.props; // eslint-disable-line no-shadow 
const styles = require('./InfoBar.scss'); 
return (
    <div className={styles.infoBar + ' well'}> 
    <div className="container"> 
     This is an info bar 
     {' '} 
     <strong>{info ? info.message : 'no info!'}</strong> 
     <span className={styles.time}>{info && new Date(info.time).toString()}</span> 
     <button className="btn btn-primary" onClick={load}>Reload from server</button> 
    </div> 
    </div> 
); 
} 
} 
+0

恐怕你碰到相同來源的限制,當您執行對遠程端點的異步HTTP請求。看看[公共維基有關同源規避](http://stackoverflow.com/questions/3076414/ways-to-circumvent-the-same-origin-policy),也許你會得到一個想法如何代理您的請求或以另一種方式克服限制。 –

+0

我已經使用該入門工具包,並且您的代碼看起來正確。我同意上面的@Rishat ......看起來你做的都是正確的,但是你可能正在做一個失敗的跨域REST調用。 「MIDDLEWARE ERROR」之後,您是否在控制檯中獲得更多信息? –

+0

我沒有得到交叉原點錯誤,但我確實得到「無法讀取屬性'承諾'的未定義」錯誤。 API適用於跨域訪問。 – user1820017

回答

-1

這僅僅是減速機。你會想創建一個動作。一個動作會觸發將使Redux商店更新其狀態的事件。終極版的是這樣的基本流程是這樣:

  • 安裝組件
  • 派遣行動
  • 反過來
  • 調度操作將更新通過Provider組件商店
  • 這將觸發重新-render組件。

以下是使用fetch的基本示例。

import fetch from 'isomorphic-fetch'; 

export function getUsers() { 
    return dispatch => { 
    dispatch({ type: REQUEST_USERS }); 

    return fetch('/api/v1/users') 
     .then(res => res.json()) 
     .then(users => { 
     dispatch({ type: RECEIVE_USERS, payload: users }); 
     return users; 
     }); 
    } 
} 

然後你可以在你的組件級別的項目中調用它。

import { getUsers } from 'actions/users'; 

class UserList extends Component { 
    componentDidMount() { dispatch(getUsers()) } 
} 

退房的example

+0

我有上面的代碼的客戶端中間件,也與該示例如果我打電話localhost api的作品 – user1820017

+0

,但它不適用於外部api調用。 localhost api有這樣的代碼導出默認函數loadInfo(){ 返回新的Promise((resolve)=> { resolve({來自api服務器', time:Date.now() } ); }); } – user1820017

+0

這不是一個正確的答案,因爲他正在使用redux-tunk作爲中間件。並打破流動 – JoseAPL