2015-11-24 17 views
52

में AJAX अनुरोध कैसे करें, मुझे पता है कि मुझे कार्रवाई बनाने में अनुरोध लिखना है। अनुरोध जमा करने के लिए कार्रवाई में वादे का उपयोग कैसे करें? मुझे कार्रवाई में डेटा मिल रहा है। फिर नया राज्य reducer में बनाया गया है। कनेक्ट में बाध्य कार्रवाई और reducer। लेकिन मुझे नहीं पता कि अनुरोध के लिए वादे का उपयोग कैसे करें।रेडक्स

कार्रवाई

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; 
    }) 
    }; 
} 

प्रसारण

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; 

कंटेनर कैसे प्रदर्शन डेटा कंटेनर में?

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; 

उत्तर

12

आप कॉलबैक अंदर dispatch उपयोग करने के लिए सक्षम होना चाहिए (यदि आप एक तर्क के रूप में यह पारित): अब

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

: कार्रवाई के लिए dispatch पारित फिर

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

, , आपको reducer में action.data संपत्ति तक पहुंच प्राप्त करनी चाहिए:

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

धन्यवाद, लेकिन अब मुझे चेतावनी मिल रही है: असफल प्रोपटाइप: आवश्यक प्रोप 'किताबें' 'booksPage' में निर्दिष्ट नहीं थीं। 'कनेक्ट (बुकपेज)' की रेंडर विधि देखें। चेतावनी @ (प्रोग्राम): 45 (प्रोग्राम): 45 चेतावनी: getDefaultProps केवल क्लासिक React.createClass परिभाषाओं पर उपयोग किया जाता है। इसके बजाय 'defaultProps' नाम की एक स्थिर संपत्ति का उपयोग करें। –

+0

क्या आपने 'action.data' को राज्य में घटा दिया था? –

+0

ऑब्जेक्ट.साइन ({}, राज्य, { पुस्तकें: action.data.books, लेखकों: action.data.authors }); –

49

चूंकि आप पहले से ही रेडक्स का उपयोग कर रहे हैं, तो आप redux-thunk मिडलवेयर लागू कर सकते हैं जो आपको एसिंक क्रियाओं को परिभाषित करने की अनुमति देता है।

स्थापना & उपयोग: 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

आप Redux Documentation

यहाँ async कार्रवाई के लिए कम करने का एक उदाहरण में वर्णित Async क्रियाओं का उपयोग करना चाहिए।

const booksReducer = (state = {}, action) => { 
    switch (action.type) { 
    case 'RESOLVED_GET_BOOK': 
     return action.data; 
    default: 
     return state; 
    } 
}; 

export default booksReducer; 

और फिर आप अपना असिंक एक्शन बनाते हैं।

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 
    } 
} 

कई नोट्स:

  • हम redux-thunk मिडलवेयर का उपयोग करके कार्रवाई में वादा लौट सकता है (वस्तु के बजाय)।
  • jQuery AJAX लाइब्रेरी का उपयोग न करें। विशेष रूप से ऐसा करने के लिए अन्य लाइब्रेरी का उपयोग करें (उदा। Fetch())। मैं axios http client का उपयोग करता हूं।
  • याद रखें, रेडक्स में आप केवल reducer में शुद्ध फ़ंक्शन का उपयोग करते हैं। Reducer के अंदर AJAX कॉल मत बनाओ।
  • रेडक्स डॉक्स से पूरी मार्गदर्शिका पढ़ें।
7

आप कार्यकर्ताओं को "शुद्ध" रखने के लिए चिंताओं को अलग करना चाहते हैं।

समाधान; कुछ मिडलवेयर लिखें। उदाहरण के लिए इसे लें (superagent का उपयोग कर)।

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); 
}; 

यह सब मॉड्यूल में रखें।

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

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

संपत्ति 'एजेंट' मिडलवेयर, जो नेटवर्क पर निर्माण अनुरोध भेजता द्वारा उठाया जाएगा, फिर भेजे डिस्पैच:

अब, आप एक एक्शन निर्माता 'प्रमाणन' कहा जाता है हो सकता है आपके स्टोर के परिणामस्वरूप।

आपका कम करने में यह सब, संभालती है आप हुक को परिभाषित करने के बाद: आपके विचार तर्क में

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; 
    } 
}; 

अब यह सब इंजेक्षन। मैं एक उदाहरण के रूप में प्रतिक्रिया का उपयोग कर रहा हूँ।

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); 

यह सब आप पहले से ही webpack, रोलअप या कुछ का उपयोग कर, वेनिला js को es2015 से transpile और प्रतिक्रिया करने के लिए, एक पाइप लाइन की स्थापना का तात्पर्य।