2016-05-25 9 views
2

So habe ich diese einfache async Request Action Creator mit axios für Anfragen und redux-thunk, um Aktionen zu versenden. Ich möchte den gleichen Aktionsersteller für verschiedene Anforderungen erneut verwenden - so hat jede Anfrage ihren eigenen Status. Ich werde versuchen, Code zu zeigen und dann mehr zu erklären. Hier ist meine Aktion SchöpferReusing reduction-reactive async Anfrage Aktion Creator/Reducer

function responseOK(response){ 
    return { 
    type: RESPONSE_OK, 
    payload: response, 
    } 
} 

function loadingChangedStatus(isLoading) { 
    return { 
    type: IS_LOADING, 
    isLoading: isLoading, 
    } 
} 

function handleError(errorID){ 
    return { 
    type: HANDLE_ERROR, 
    errorID: errorID, 
    } 
} 



export function makeRequest(URL){ 

    return function(dispatch, getSate){ 

     dispatch(loadingChangedStatus(true)); 

     axios.get(URL) 
     .then(function(response){ 
      dispatch(loadingChangedStatus(false)); 
      dispatch(responseOK(response)); 

     }) 
     .catch(function (response) { 
      dispatch(loadingChangedStatus(false)); 
      dispatch(handleError('connection_error')); 
     }); 
    } 

} 

Und mein Minderer reducerRequest:

export default function(state = {isLoading:false, payload:false,errorID:false}, action){ 

    switch (action.type) { 

    case IS_LOADING: 
     return Object.assign({}, state, { 
     isLoading: action.isLoading, 
     }); 
     break; 

    case RESPONSE_OK: 
     return Object.assign({}, state, { 
      isLoading: state.isLoading, 
      payload: action.payload, 
     }); 
     break; 

    case HANDLE_ERROR: 
     return Object.assign({}, state, { 
      isLoading: state.isLoading, 
      payload: action.payload, 
      errorID:action.errorID, 
     }); 
     break; 

    default: 
     return state; 
    } 

} 

HIER STARTET MEIN PROBLEM

Ich kombiniere Reduzierungen wie so:

import { combineReducers } from 'redux'; 
import Request from "./reducerRequest"; 

const rootReducer = combineReducers({ 
    // I WANT EACH OF THESE TO BE SEPARATE INSTANCE BUT USE THE SAME ACTION CREATOR/REDUCER 
    defaults: Request, 
    updates: Request, 
}); 

export default rootReducer; 

I n meine Komponente:

function mapStateToProps({defaults, updates}){ 
    return {defaults, updates} 
} 

function mapDispatchToProps(dispatch){ 
    return bindActionCreators({ makeRequest}, dispatch); 
} 

PROBLEM: Ich möchte meinen Aktionsersteller für verschiedene Anforderungen erneut verwenden. Wie kann ich

  1. Anruf makeRequest('www.defaults.com') und es endet in defaults
  2. Anruf makeRequest('www.updates.com') und es endet in updates

nun die einzige Möglichkeit, bis ich Bild, dies zu lösen wäre für jeden zu schreiben Fordern Sie einen eigenen Aktionsersteller und einen eigenen Reducer an - nur eine Menge Kopierpaste - das fühlt sich nicht richtig an.

Wie kann ich meinen Aktionsersteller und Reduzierer wiederverwenden, um zwei separate Instanzen von defaults und updates in meiner Komponente zu erstellen?

Antwort

1

Sie können Ihre Minderer Aktionen pro Aktion Präfix:

export default function(namespace) 
    return function(state = {isLoading:false, payload:false,errorID:false}, action){ 

    switch (action.type) { 

    case namespace + IS_LOADING: 
     return Object.assign({}, state, { 
     isLoading: action.isLoading, 
     }); 
     break; 

    case namespace + RESPONSE_OK: 
     return Object.assign({}, state, { 
      isLoading: state.isLoading, 
      payload: action.payload, 
     }); 
     break; 

    case namespace + HANDLE_ERROR: 
     return Object.assign({}, state, { 
      isLoading: state.isLoading, 
      payload: action.payload, 
      errorID:action.errorID, 
     }); 
     break; 

    default: 
     return state; 
    } 
} 
} 

und fügen Sie dann den Namespace

function responseOK(namespace, response){ 
    return { 
    type: namespace + RESPONSE_OK, 
    payload: response, 
    } 
} 


const rootReducer = combineReducers({ 
    // I WANT EACH OF THESE TO BE SEPARATE INSTANCE BUT USE THE SAME ACTION CREATOR/REDUCER 
    defaults: Request("DEFAULTS_"), 
    updates: Request("UPDATES_"), 
}); 

und dann den Namespace verwenden, wenn Sie die Rufnummer wählen fordert

call makeRequest('DEFAULTS_', 'www.defaults.com') and it ends up in defaults 
call makeRequest('UPDATES_', 'www.updates.com') and it ends up in updates 

HTH

+0

C ool, danke, es scheint zu funktionieren. Ich bin noch neu bei Redux/React. Kannst du mich bitte aufklären wenn möglich. Wird dies in Richtung Best Practice oder nur eine Art von Hack oder Workaround betrachtet, um Lücken in Redux/React zu schließen? – fjckls

+1

Es ist ziemlich Standard. Das Standard-Dienstprogramm "combineReducer" gibt allen Reducer-Funktionen für Kinder die Möglichkeit, auf eine bestimmte Aktion zu reagieren. Wenn Sie also in Ihrer Reducer-Struktur den gleichen Reducer zweimal verwenden, müssen Sie unterscheiden, ob Sie antworten möchten oder nicht. Außerdem gibt es eine Reihe ähnlicher action/reducer wrapper Dienstprogramme, die in meinem Redux addons-Katalog unter https://github.com/markerikson/redux-ecosystem-links aufgeführt sind. Denken Sie, es gibt einige, die viel von dieser Arbeit für Sie schon tun können. – markerikson

Verwandte Themen