Reagieren (von create-react-app) mit MobX. Verwenden von Axios für asynchrone Back-End-API-AufrufeRefactoring bricht Anfangszustand
Dieser Code funktioniert. Der Anfangszustand (Array von Problemen) wird aufgefüllt, und die Webseite, auf der diese Komponente präsentiert wird, wird mit dem ursprünglichen Inhalt aus dem Status gerendert.
import { observable, computed, autorun, reaction } from 'mobx'
import axios from 'axios'
class IssuesStore {
@observable issues = []
constructor() {
autorun(() => console.log("Autorun:" + this.buildIssues))
reaction(
() => this.issues,
issues => console.log("Reaction: " + issues.join(", "))
)
}
getIssues(data) {
return data.map((issue) => ({title: issue.name, url: issue.url, labels: issue.labels}))
}
@computed get buildIssues() {
const authToken = 'token ' + process.env.REACT_APP_GH_OAUTH_TOKEN
axios.get(`https://api.github.com/repos/${process.env.REACT_APP_GH_USER}/gh-issues-app/issues`,
{ 'headers': {'Authorization': authToken} })
.then(response => {
console.log(response)
this.issues = this.getIssues(response.data)
return this.issues
})
.catch(function(response) {
console.log(response)
})
}
}
export default IssuesStore
In einem Versuch API-Aufruf Versprechen von einzelnen Komponenten und speichert zu trennen, zog ich den axios Anruf in eine separate JS-Datei aus, als eine Sammlung von Funktionen:
import axios from 'axios'
const authToken = 'token ' + process.env.REACT_APP_GH_OAUTH_TOKEN
export function loadIssues() {
return this.apiPromise(
`https://api.github.com/repos/${process.env.REACT_APP_GH_USER}/gh-issues-app/issues`,
{ 'headers': {'Authorization': authToken} }
)
}
export function apiPromise(endpoint, options) {
return axios.get(endpoint, options)
.then((response) => {
// console.log("response: " + JSON.stringify(response, null, 2))
return response.data.map((issue) => ({title: issue.name, url: issue.url, labels: issue.labels}))
})
.catch(function(response) {
console.log(response)
})
}
Nun, mein Speicher sieht wie folgt aus:
import { observable, computed, autorun, reaction } from 'mobx'
import * as github from '../api/github'
class IssuesStore {
@observable issues = []
constructor() {
autorun(() => console.log("Autorun:" + this.buildIssues))
reaction(
() => this.issues,
issues => console.log("Reaction: " + issues.join(", "))
)
}
@computed get buildIssues() {
this.issues = github.loadIssues().data
return this.issues
}
}
export default IssuesStore
Viel kleiner ... aber die Webseite nun einen Fehler wirft, weil es jetzt den Anfangszustand issues
alssieht 0 beim ersten Rendern.
Uncaught TypeError: Cannot read property 'map' of undefined
Das Versprechen erfolgreich später vervollständigt (wie es sein sollte), aber dann ist es zu spät. Sicher, ich kann ein paar null
Checks in meinen Rendering-Komponenten einrichten, um .map
oder andere solche Funktionen nicht auf leeren oder noch nicht definierten Variablen laufen zu lassen.
Aber warum funktioniert der Code ohne anfängliche Renderfehler vor dem Refactoring, und nicht nach? Ich dachte, das Refactoring würde den gleichen Logikfluss beibehalten, aber ich muss etwas übersehen haben.
Dank! Hat funktioniert. Mein Verständnis von Versprechungen war nicht gut genug, um zu verstehen, warum ich ein anderes '.then()' auf dem zurückgegebenen Versprechen brauchte, um meine Daten zu bekommen. Ich nahm an, dass das '' then() ', das in der Versprechung selbst definiert wurde, genug war, um zu holen, was ich innerhalb der Antwort brauchte. – changingrainbows