2017-03-29 2 views
1

ich folgendes Asynchron-Aktion Schöpfer (mit redux-Thunk) haben:Wie verwandelst du Redux-Thunk Action Creator in Promise?

export const nextPupil =() => { 
    return (dispatch, getState) => { 
    const {activeSentence, sentencesList} = getState(); 
    //... some more code 
    const nextActive = pupilList[nextIndex]; 

    dispatch({ type: "UPDATE_ACTIVE", payload: nextActive }); 
    } 
}; 

Ich brauche aber diese Aktion ein Versprechen zurückzukehren, da ich für seine Vollendung in einer meiner Komponenten warten müssen, bevor Sie etwas anderes (siehe this question für eine detailliertere Beschreibung meines Problems)

Wie könnte ich diese Aktion in ein Versprechen verwandeln und immer noch Redux-Thunk verwenden? Vielen Dank im Voraus.

edit:

Ich weiß, dass ich versuche, den Zustand des Eingabefeldes lokal in meiner Komponente zu speichern, das heißt, nicht in Redux. Denn wenn ich den Wert des Eingabefeldes direkt an den Redux-Speicher binden würde, wäre er nicht mehr editierbar. Ich möchte jedoch, dass der Benutzer in der Lage ist, das Eingabefeld zu bearbeiten und dann bei der Übergabe den bearbeiteten Wert in meinem Redux-Speicher zu speichern. Wenn ich Objekte direkt verbinde, kann der Benutzer Werte nicht ändern/bearbeiten.

Antwort

3

Ich glaube, Sie missverstehen die Datenströme durch Redux. Ich nehme an, wenn Sie die Aktion in ein Versprechen verwandeln wollen, möchten Sie, dass dieses Versprechen aufgelöst wird, wenn der Redux-Status aktualisiert wurde - dies scheint bei Ihrer anderen Frage der Fall zu sein. Dies ist nicht allgemein, wie redux entworfen ist, um zu arbeiten.

Wenn Sie eine Aktion versenden, wird das Geschäft aktualisiert, und dann werden die Requisiten in Ihren Komponenten aktualisiert, die aus dem Geschäft kommen. Alles, was Sie tun müssen, ist diese Requisiten in Ihren Komponenten zu verwenden, und wann immer die Requisiten updaten, wird auch Ihre Komponente.

In Ihrer ersten Frage Code war:

onSubmit(e) { 
    e.preventDefault(); 
    this.props.nextSentence(); //this is async 

    this.setState({ //this is not yet updating with the right values then 
     inputField: this.props.activePupil.name 
    }); 
} 

Das Problem, das Sie haben, ist, dass activePupil Teil Ihres redux Speicher ist, aber Sie versuchen, es auch in den Zustand Ihrer Komponente zu speichern. Das ist eine schlechte Idee, weil Sie für Ihren Staat keine einzige Quelle der Wahrheit mehr haben.

Der bessere Ansatz ist es, einfach this.props.activePupil wo immer es benötigt wird, z.

Jetzt, wenn Sie die Aktion versenden, sobald der Laden aktualisiert wird, wird auch Ihre Komponente aktualisiert. Wenn Sie dann benötigen, können Sie Ihrem Geschäft eine loading -Eigenschaft hinzufügen, so dass Sie dem Benutzer anzeigen können, dass etwas passiert, und senden Sie diese von Ihrem Thunk, bevor Sie Async-Arbeit ausführen, und.wiederherstellen, wenn UPDATE_ACTIVE ausgelöst wird.

export const nextPupil =() => { 
    return (dispatch, getState) => { 
     dispatch({ type: "PUPIL_UPDATING }); 
     const {activeSentence, sentencesList} = getState(); 
     //... some more code 
     const nextActive = pupilList[nextIndex]; 

     dispatch({ type: "UPDATE_ACTIVE", payload: nextActive }); 
    } 
}; 

Edit 1

Es ein wenig Gedanken über den richtigen Ansatz, um das Problem unten genommen hat, aber ich denke, dass ich auf eine vernünftige Art und Weise angesiedelt habe, es zu erreichen, während die Datenintegrität zu gewährleisten. Es beinhaltet Formeingabe in Ihrem Geschäft, für die nicht jeder ein Fan ist, aber für mich kein Problem ist.

Wie auch immer ...Wir brauchen ein neues Minderer für Benutzereingabe Handhabung - es wird sehr einfach sein und auf zwei Aktionen reagieren - die „UPDATE_ACTIVE“ Aktion, die Sie bereits haben, und eine „NAME_UPDATED“ Aktion:

const updatedName = (state = '', action) => { 
    switch (action.type) { 
    case 'UPDATE_ACTIVE': 
     return action.payload.name; 
    case: 'NAME_UPDATED': 
     return action.payload.updatedName; 
    default: 
     return state; 
    } 
}; 

Dann brauchen wir eine einfache Aktion Schöpfer:

const inputChanged = updatedName => ({ 
    type: 'NAME_UPDATED', 
    payload: { updatedName } 
}); 

Jetzt in unserer Komponente werden wir die neu geschaffenen Zustand und Aktion Schöpfer verwenden, um unseren Beitrag zu verwalten (connect sie nur in wie üblich) - viel Code hier fehlt aber sollte es genug sein, um das zu bekommen Idee.

class Whatever extends React.Component { 
    constructor() { 
     super(); 
     this.handleChange= this.handleChange.bind(this); 
    } 

    handleChange(event) { 
     this.props.inputChanged(event.target.value); 
    } 

    render() { 
     return (
      <input type="text" value={this.props.updatedName} onChange={this.handleChange} /> 
     ); 
    } 
} 

Ich hoffe, dass es Sinn macht!

Edit 2:

Wenn Sie die Eingabe auf Komponente Zustand speichern möchten, anstatt innerhalb des redux speichern, dann denke ich, dieser Ansatz funktionieren sollte. Es verwendet die componentWillReceiveProps lifecycle hook - um den Komponentenstatus festzulegen, d. H. Den Eingangswert, wenn sich die activePupil Requisite ändert. Dies wird jedes Mal aufgerufen, wenn die Requisiten aktualisiert werden, kann aber auch aufgerufen werden, wenn es keine Requisitenänderungen gibt. Daher benötigen wir eine Logik, um zu entscheiden, ob die Requisite updatedPupilName aktualisiert werden soll. Um dies zu erreichen, vergleichen wir unsere aktuellen props.activePupil.name mit der nextProps.activePupil.name und aktualisieren nur den Zustand, wenn sie unterschiedlich sind. Wenn Sie eine ID-Eigenschaft auf Ihre Schüler haben, wäre dies wahrscheinlich besser für den Vergleich geeignet.

class Whatever extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      updatedPupilName: props.activePupil.name 
     }; 
     this.handleChange= this.handleChange.bind(this); 
    } 

    componentWillReceiveProps(nextProps) { 
     if (nextProps.activePupil.name !== this.props.activePupil.name) { 
      this.setState({ 
       updatedPupilName: nextProps.activePupil.name 
      }); 
     } 
    } 

    handleChange(event) { 
     this.setState({ 
      updatedPupilName: event.target.value 
     }); 
    } 

    render() { 
     return (
      <input type="text" value={this.state.updatedPupilName} onChange={this.handleChange} /> 
     ); 
    } 
} 
+0

Dies ist eine wirklich gut erklärte Antwort, netter Job :) –

+0

Vielen Dank für die aufwendige Antwort! Mein Problem ist, dass wenn ich 'this.props.activePupil.name' direkt benutze, es für den Benutzer nicht editierbar ist, da es an den Wert des Redux-Shops gebunden ist. Aber ich möchte, dass der Benutzer in der Lage ist, den Wert des Eingabefeldes zu ändern und im Laden zu speichern. Deshalb setze ich einen Zustand des Eingabefeldes dazwischen und gebe den Wert des Geschäfts in das Eingabefeld ein, und bei submit möchte ich das im Speicher speichern. Oder missverstehe ich das ernst? –

+0

Ich werde meine Antwort mit etwas mehr Details bearbeiten. –