programing tip

redux에서 AJAX 요청을 만드는 방법

itbloger 2020. 11. 28. 08:50
반응형

redux에서 AJAX 요청을 만드는 방법


내가 아는 모든 것을 위해 행동 생성 요청을 작성해야합니다. 요청을 제출하기 위해 실행중인 Promise를 사용하는 방법은 무엇입니까? 데이터가 작동 중입니다. 그런 다음 감속기에 새로운 상태가 생성됩니다. 연결 작업과 감속기를 바인딩합니다. 하지만 요청에 promise를 사용하는 방법을 모르겠습니다.

동작

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;

이미 redux를 사용 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 };
}

Redux 문서에 설명 된 비동기 작업을 사용해야합니다.

다음은 비동기 작업을위한 감속기의 예입니다.

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 미들웨어를 사용하여 Promise (Object 대신)를 반환 할 수 있습니다.
  • jQuery ajax 라이브러리를 사용하지 마십시오. 이를 위해 특별히 다른 라이브러리를 사용하십시오 (예 : fetch ()). 내가 사용 Axios의 HTTP 클라이언트를 .
  • redux에서는 감속기에서만 순수 기능을 사용한다는 것을 기억하십시오. 감속기 내부에서 ajax 호출을하지 마십시오.
  • redux 문서에서 전체 가이드를 읽으십시오.

dispatch콜백 내에서 사용할 수 있어야합니다 (인수로 전달하는 경우).

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

그런 다음 dispatch조치로 전달 하십시오.

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

이제 action.data감속기 속성에 액세스 할 수 있어야합니다 .

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

액션 제작자를 "순수"하게 유지하기 위해 우려 사항을 분리 할 수 ​​있습니다.

해결책; 미들웨어를 작성하십시오. 예를 들어 (수퍼 에이전트 사용) 이것을 사용하십시오.

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

이 모든 것을 모듈에 넣으십시오.

이제 'auth'라는 액션 생성자가있을 수 있습니다.

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

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

The property 'agent' will be picked up by the middleware, which sends the constructed request over the network, then dispatches the incoming result to your store.

Your reducer handles all this, after you define the hooks:

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

Now inject all this into your view logic. I'm using react as an example.

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

All of this implies you already set up a pipeline using webpack,rollup or something, to transpile from es2015 and react, to vanilla js.

참고URL : https://stackoverflow.com/questions/33891669/how-to-make-ajax-request-in-redux

반응형