2015-11-24 33 views
52

Bildiğim kadarıyla, eylem oluşturmak için istek yazmam gerekiyor. Bir istek göndermek için hareket halinde bir söz nasıl kullanılır? Verileri harekete geçiriyorum. Daha sonra redüktörde yeni durum yaratılır. Bağlantıda bağlama eylemi ve redüktör. Ama istek için nasıl söz vereceğimi bilmiyorum.Redux'ta AJAX isteği nasıl yapılır

Eylem

import $ from 'jquery'; 
export const GET_BOOK = 'GET_BOOK'; 

export default function getBook() { 
    return { 
    type: GET_BOOK, 
    data: $.ajax({ 
     method: "GET", 
     url: "/api/data", 
     dataType: "json" 
    }).success(function(data){ 
     return data; 
    }) 
    }; 
} 

Redüktör

import {GET_BOOK} from '../actions/books'; 

const booksReducer = (state = initialState, action) => { 
    switch (action.type) { 
    case GET_BOOK: 
     return state; 
    default: 
     return state; 
    } 
}; 

export default booksReducer; 

Konteyner Nasıl ekran veri kapta?

import React, { Component, PropTypes } from 'react'; 
import { connect } from 'react-redux'; 
import getBook from '../actions/books'; 
import Radium from 'radium'; 
import {Link} from 'react-router'; 

function mapStateToProps(state) { 
    return { 
    books: state.data.books, 
    }; 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    getBooks:() => dispatch(getBook()), 
    }; 
} 

@Radium 
@connect(mapStateToProps, mapDispatchToProps) 
class booksPage extends Component { 
    static propTypes = { 
    getBooks: PropTypes.func.isRequired, 
    books: PropTypes.array.isRequired, 
    }; 

    render() { 
    const {books} = this.props; 
    return (
     <div> 
     <Link to={`/authors`}><MUIButton style="flat">All Authors</MUIButton></Link> 
     <ul> 
      {books.map((book, index) => 
      <li key={index}> 
       <Link to={`/book/${book.name}`}><MUIButton style="flat"><div class="mui--text-black mui--text-display4"> 
       "{book.name}"</div></MUIButton></Link> 
       <Link to={`/author/${book.author}`}><MUIButton style="flat"><div class="mui--text-black mui--text-display4"> 
       {book.author}</div></MUIButton></Link> 
      </li> 
     )} 
     </ul> 
     </div> 
    ); 
    } 
} 

export default booksPage; 

cevap

12
Sen (bir argüman olarak geçmek ise) callback'inde içine dispatch kullanmak mümkün olmalıdır

:

export default function getBook(dispatch) { 
    $.ajax({ 
     method: "GET", 
     url: "/api/data", 
     dataType: "json" 
    }).success(function(data){ 
     return dispatch({type:'GET_BOOK', data: data}); 
    }); 
} 

Sonra eyleme dispatch geçmesi: Artık

function mapDispatchToProps(dispatch) { 
    return { 
    getBooks:() => getBook(dispatch), 
    }; 
} 

redüktördeki action.data özelliğine erişiminiz olmalıdır:

const booksReducer = (state = initialState, action) => { 
    switch (action.type) { 
    case GET_BOOK: 
     //action.data <--- here 
     return state; 
    default: 
     return state; 
    } 
}; 
+0

teşekkürler, ama şimdi ben Uyarı olsun. 45 (programı): 'Bağlan (booksPage)' .warning @ (programı) render metodunu kontrol 45 Uyarı: getDefaultProps yalnızca klasik React.createClass tanımlarında kullanılır. Bunun yerine "defaultProps" adlı bir statik özellik kullanın. –

+0

Eğer duruma 'action.data' azaltmak mü? –

+0

Object.assign ({}, state, { kitaplar: action.data.books, yazarları: action.data.authors }); –

49

Zaten redux kullandığınız için, async eylemlerini tanımlamanıza olanak veren redux-thunk ara yazılım uygulayabilirsiniz.

Kurulum & kullanımı: Redux-thunk

export function fetchBook(id) { 
return dispatch => { 
    dispatch(setLoadingBookState()); // Show a loading spinner 
    fetch(`/book/${id}`, (response) => { 
    dispatch(doneFetchingBook()); // Hide loading spinner 
    if(response.status == 200){ 
     dispatch(setBook(response.json)); // Use a normal function to set the received state 
    }else { 
     dispatch(someError) 
    } 
    }) 
} 
} 

function setBook(data) { 
return { type: 'SET_BOOK', data: data }; 
} 
20

Sen Burada Redux Documentation

zaman uyumsuz işlem için redüktör örneği açıklanan zaman uyumsuz Eylemler kullanmalıdır. ve ardından Eşzamansız Eyleminizi oluşturun.

export const getBook() { 
    return fetch('/api/data') 
    .then(response => response.json()) 
    .then(json => dispatch(resolvedGetBook(json))) 
} 

export const resolvedGetBook(data) { 
    return { 
    type: 'RESOLVED_GET_BOOK', 
    data: data 
    } 
} 

Çeşitli Notlar:

  • Biz redux-thunk ortakatmanını kullanarak eylem (yerine Nesne) Promise geri dönebilirler.
  • jQuery ajax kütüphanesini kullanmayın. Bunu yapmak için özel olarak başka kütüphane kullanın (ör. Fetch()). axios http client kullanıyorum.
  • Redux olarak, redüktörde sadece saf fonksiyonu kullanın. Ajax azaltıcı içinde arama yapmayın.
  • Tüm kılavuzu redux belgelerinden okuyun.
7

Eylem oluşturanları "saf" tutmak için endişeleri ayırmak isteyebilirsiniz.

Çözeltiler; bazı ara katman yaz. Örneğin bunu al (süper arındırıcı kullanarak).

import Request from 'superagent'; 

const successHandler = (store,action,data) => { 

    const options = action.agent; 
    const dispatchObject = {}; 
    dispatchObject.type = action.type + '_SUCCESS'; 
    dispatchObject[options.resourceName || 'data'] = data; 
    store.dispatch(dispatchObject); 
}; 

const errorHandler = (store,action,err) => { 

    store.dispatch({ 
     type: action.type + '_ERROR', 
     error: err 
    }); 
}; 

const request = (store,action) => { 

    const options = action.agent; 
    const { user } = store.getState().auth; 
    let method = Request[options.method]; 

    method = method.call(undefined, options.url) 

    if (user && user.get('token')) { 
     // This example uses jwt token 
     method = method.set('Authorization', 'Bearer ' + user.get('token')); 
    } 

    method.send(options.params) 
    .end((err,response) => { 
     if (err) { 
      return errorHandler(store,action,err); 
     } 
     successHandler(store,action,response.body); 
    }); 
}; 

export const reduxAgentMiddleware = store => next => action => { 

    const { agent } = action; 

    if (agent) { 
     request(store, action); 
    } 
    return next(action); 
}; 

Tüm bunları bir modülde koyun.

export const auth = (username,password) => { 

    return { 
     type: 'AUTHENTICATE', 
     agent: { 
      url: '/auth', 
      method: 'post', 
      resourceName: 'user', 
      params: { 
       username, 
       password 
      } 
     } 
    }; 
}; 

ağ üzerinden inşa isteği gönderir katman tarafından alınmayı olacak mülkiyet 'ajan', Gelen gönderir: Artık

, sen 'auth' olarak adlandırılan bir eylem yaratıcısı olabilir Mağazanızla sonuçlanır.

kancaları tanımlamak erdikten sonra redüktör bütün bunlar, kolları: Görünüm mantığı içine

import { Record } from 'immutable'; 

const initialState = Record({ 
    user: null, 
    error: null 
})(); 

export default function auth(state = initialState, action) { 

    switch (action.type) { 

     case 'AUTHENTICATE': 

      return state; 

     case 'AUTHENTICATE_SUCCESS': 

      return state.merge({ user: action.user, error: null }); 

     case 'AUTHENTICATE_ERROR': 

      return state.merge({ user: null, error: action.error }); 

     default: 

      return state; 
    } 
}; 

Artık tüm bu enjekte edin. Örnek olarak tepki alıyorum.

import React from 'react'; 
import ReactDOM from 'react-dom'; 

/* Redux + React utils */ 
import { createStore, applyMiddleware, bindActionCreators } from 'redux'; 
import { Provider, connect } from 'react-redux'; 

// thunk is needed for returning functions instead 
// of plain objects in your actions. 
import thunkMiddleware from 'redux-thunk'; 

// the logger middleware is useful for inspecting data flow 
import createLogger from 'redux-logger'; 

// Here, your new vital middleware is imported 
import { myNetMiddleware } from '<your written middleware>'; 

/* vanilla index component */ 
import _Index from './components'; 

/* Redux reducers */ 
import reducers from './reducers'; 

/* Redux actions*/ 
import actionCreators from './actions/auth'; 


/* create store */ 
const store = createStore(
    reducers, 
    applyMiddleware(
     thunkMiddleware, 
     myNetMiddleware 
    ) 
); 

/* Taint that component with store and actions */ 
/* If all goes well props should have 'auth', after we are done */ 
const Index = connect((state) => { 

    const { auth } = state; 

    return { 
     auth 
    }; 
}, (dispatch) => { 

    return bindActionCreators(actionCreators, dispatch); 
})(_Index); 

const provider = (
    <Provider store={store}> 
     <Index /> 
    </Provider> 
); 

const entryElement = document.getElementById('app'); 
ReactDOM.render(provider, entryElement); 

Bütün bunlar zaten vanilya js için, es2015 den transpile ve tepki, webpack, toplaması falan kullanarak bir boru hattı kurmak anlamına gelir. books` değil booksPage` `belirtildi` Gerekli pervane: Başarısız PropType:

İlgili konular