62
задан 23 August 2016 в 13:24

4 ответа

Вы могли бы хотеть разделить проблемы, сохранить создателей действия "чистыми".

Решение; запишите некоторое промежуточное программное обеспечение. Возьмите это, например (использующий суперагента).

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, свертку или что-то, чтобы транссложить от es2015 и реагировать, к ванили js.

7
ответ дан 31 October 2019 в 14:09

Так как Вы уже используете возвращение, можно подать заявку 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 };
}
54
ответ дан 31 October 2019 в 14:09

Необходимо использовать Асинхронные Действия, описанные в Документация Возвращения

Здесь пример редуктора для асинхронного действия.

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

Несколько Примечаний:

  • Мы могли возвратить Обещание (вместо Объекта) в действии при помощи промежуточного программного обеспечения преобразователя возвращения.
  • не используют jQuery ajax библиотека. Пользуйтесь другой библиотекой специально для выполнения этого (например, выборка ()). Я использую axios http клиент .
  • Помнят, в возвращении, Вы только используете чистую функцию в редукторе. Не выполняйте вызов ajax в редукторе.
  • Read полное руководство из документов возвращения.
26
ответ дан 31 October 2019 в 14:09

Необходимо смочь использовать 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;
  }
};
13
ответ дан 31 October 2019 в 14:09

Другие вопросы по тегам:

Похожие вопросы: