2017-05-16 2 views
2

Ich bin neu in Redux Saga, von Redux Thunk kommen. In einigen Situationen muss ich wissen, ob ein API-Aufruf in der Sicht, von der aus ich die Aktion aufgerufen habe, fehlschlägt oder erfolgreich ist. Mit Redux Thunk würde ich so etwas wie das Folgende machen.Umgang mit Redux Saga-Ergebnis in der Ansicht, aus der Aktionsaufruf stammt

Meine Komponente und Aktion Schöpfer würden wie folgt aussehen:

class MyComponent extends Component { 

    componentDidMount() { 
    this.props.actions.fetchItems() 
    .then(result => { 
     if (result.status === 'OK') { 
      console.log('Request succeeded, take particular action in this view') 
     } 
     else { 
      console.log('Request failed, take other action in this view') 
     } 
    }) 
    } 

    render() { 
    return (
     <div>My view</div> 
    ) 
    } 
} 


const mapStateToProps = (state, ownProps) => { 
    return { 
     items: state.items, 
    } 
} 

const mapDispatchToProps = dispatch => { 
    return { 
     actions: bindActionCreators({ 
      ...actions, 
     }, dispatch), 
    } 
} 


export default connect(
    mapStateToProps, 
    mapDispatchToProps, 
)(MyComponent) 



import * as t from './actionTypes' 
import {CALL_API} from '../api' 

const xhrGetItems = (params) => (dispatch, getState) => { 
    const action = { 
     [CALL_API]: { 
      type: t.XHR_ITEMS_FETCH, 
      endpoint: `http://www.example.com/myendpoint`, 
      method: 'get', 
     } 
    } 
    return dispatch(action) 
} 

Meine API Middleware fängt alle Aktionen mit einer CALL_API Eigenschaft verwendet eine Ajax-Bibliothek, um den entsprechenden Anruf zu tätigen, dann gibt ein erfülltes Versprechen. Mein Reduzierer ist so eingerichtet, dass er jeden der möglichen Zustände des API-Aufrufs (Erfolg, Fehler, Ausstehend) behandelt. Die ganze Zeit kann ich das Ergebnis des Anrufs in meiner Ansicht überprüfen, wo es herstammt.

Also meine Frage ist, wie kann dies mit Redux Saga erreicht werden? Im Moment macht meine saga api Middleware alles, was sie tun sollte, aber wenn ich fetchItems() aus meiner Sicht anrufe, ist das Ergebnis ein einfaches JS-Objekt, also kann ich nicht überprüfen, ob es erfolgreich war oder nicht.

Es ist möglich, dass ich auch völlig falsch damit umgehe. Irgendwelche Vorschläge werden sehr geschätzt.

Antwort

2

Ein häufiges Muster mit redux und redux-saga ist das Erstellen von 3 Aktionen für einen API-Aufruf. In Ihrem Fall würde ich erstellen:

  • LIST_ITEMS_START
  • LIST_ITEMS_SUCCEEDED
  • LIST_ITEMS_FAILED

Ihre Saga etwas würde wie folgt aussehen:

function* watchListItemsStart() { 
    yield takeLatest(LIST_ITEMS_START, listItemsStartFlow) 
} 

function* listItemsStartFlow() { 
    try { 
    const result = yield call(api.getItems) 

    if (result.status === 'OK') { 
     yield put(LIST_ITEMS_SUCCEEDED, items) 
    } else { 
     throw new Error(result.error) 
    } 
    } catch (error) { 
    yield put(LIST_ITEMS_FAILED, error) 
    } 
} 

Die Sagas die sauber abstrahiert haben weg API-Nebeneffekt. Das Reduktionsmittel kann auf Zustandsverwaltung konzentrieren:

switch (action.type) { 
    case LIST_ITEMS_START: 
    return { 
     ...state, 
     isLoading: true, 
     error: null, 
     items: [], 
    } 
    case LIST_ITEMS_SUCCEEDED: 
    return { 
     ...state, 
     isLoading: false, 
     items: action.payload.items, 
    } 
    case LIST_ITEMS_FAILED: 
    return { 
     ...state, 
     isLoading: false, 
     error: action.payload.error.getMessage(), 
    } 
} 

Jetzt haben Sie alles, was Sie in Ihrem Geschäft benötigen, die ausgewählt werden können und zur Reaktion gebracht in der Komponente auf.

Ein wichtiger Punkt hier ist, dass Ihre Komponente sehr dumm wird. Es bekommt nur Requisiten und behandelt nicht das Ergebnis des API-Aufrufs (keine promise.then hier).

Ich hoffe, diese Antwort wird Ihnen helfen.

+0

Danke für Ihre Antwort @Alex. Was du beschrieben hast, ist im Grunde das, was ich eingerichtet habe. Meine Frage ist, wie man die Komponente schlau hält. Ein Anwendungsfall hierfür wäre: Benutzer sendet Daten über einen API-Aufruf. Bei erfolgreicher Anfrage leiten Sie den Benutzer zu einer anderen Seite/Komponente um (z. B. mit dem react-router 'browserHistory.push ('/ myPath') '). Normalerweise würde ich diese Umleitung innerhalb der Komponente nennen. Gibt es einen besseren Weg, dies zu tun, den ich nicht in Betracht ziehe? – Murcielago

+0

Basierend auf dem, was Sie beschrieben haben und was ich gerade eingerichtet habe, müsste ich dies tun, indem ich 'componentWillReceiveProps (nextProps)' 'this.props.isLoading &&! NextProps.isLoading 'einchecke, und dann die entsprechenden Maßnahmen gemäß' nextProps ergreifen .error' (z. B. bei Erfolg zu neuer Komponente navigieren oder Fehlermeldung bei Fehler anzeigen). Dies scheint nur ein langer Workaround für etwas Einfaches zu sein. Können Sie die Best Practices für diesen speziellen Anwendungsfall kommentieren? – Murcielago

+0

Alle Ihre Nebenwirkungen wie Routing, API-Anrufe usw. sollten in die Saga gehen. Also in der Sage, wo ich 'if (Ergebnis.Status === 'OK') 'Sie könnten die Routerlogik setzen. Sie werden Ihr Leben viel einfacher machen, wenn die Komponenten nicht smart aber dumm sind – Alex

Verwandte Themen