2016-08-05 13 views
3

Ich bin sehr neu mit React und ich versuche, die Daten vom Server mit fetch API zu rufen.Fetch Daten mit React

Wenn ich will, eine Hilfsklasse machen, die Daten wie diese

import { Promise } from 'es6-promise'; 
 
import fetch from 'isomorphic-fetch'; 
 
let responseData = response => { 
 
    return response; 
 
}; 
 

 
let getData = (dataURL, headers) => { 
 
    let result = { 
 
    data: [], 
 
    message: '' 
 
    }; 
 
    if (dataURL === null || dataURL === undefined || dataURL === '') { 
 
    result.message = 'URL is not correct'; 
 
    responseData(result); 
 
    } 
 
    fetch(dataURL, headers) 
 
    .then(response =>{ 
 
     if (response.ok) { 
 
     response.json().then(data => { 
 
      result.data = data; 
 
      result.message = response.statusText; 
 
      responseData(result); 
 
     }); 
 
     }else{ 
 
     result.message = 'Network response was not ok.'; 
 
     responseData(result); 
 
     } 
 
    }) 
 
    .catch(err => console.log(err)); 
 
}; 
 

 
exports.responseData = responseData; 
 
exports.getData = getData;

zu bekommen und immer dann, wenn die Daten verfügbar sind, werde ich das Reagieren fragen die Ansicht machen, während der Wartezeit, es wird ein Ladesymbol angezeigt.

Ich lege den Anruf innerhalb componentDidMout, aber bis es ausgeführt wird, ist das Ergebnis immer undefined.

componentDidMount() { 
 
    var self = this; 
 
    let result = util.getData('http://localhost:3001/menus'); 
 
    const { dispatch } = this.props; 
 
    // dispatch(menuActions.fetchMenusIfNeeded()); 
 
    if (result !== null && result !== undefined) { 
 
     if (this.isMounted()) { 
 
     this.setState({ 
 
      items: result.data.results 
 
     }); 
 
     } 
 
    } 
 
    }

In Angular, sobald die Daten verfügbar sind, wird es entsprechend aktualisiert werden, aber ich verstehe wirklich nicht, wie es in zu reagieren.

EDIT 1: die Hilfsklasse aktualisieren:

import { Promise } from 'es6-promise'; 
 
import fetch from 'isomorphic-fetch'; 
 

 

 
let getData = (dataURL, headers) => { 
 
    return fetch(dataURL, headers); 
 
}; 
 

 
exports.getData = getData;

Es wird immer geben einen Promise so kann ich Kette Handler für Daten in anderen Komponenten. Das einzige Problem, das ich benötige, um die Nachricht zu behandeln, ist das Lesen des Response Objekts in meinen Komponenten.

In Reaktion Komponente:

componentWillMount() { 
 
    util.getData('http://localhost:3001/menus') 
 
     .then(response =>{ 
 
     if (response.ok) { 
 
      response.json().then(data => { 
 
      console.log(data); 
 
      this.setState({ 
 
       items: data.result 
 
      }); 
 
      }); 
 
     } 
 
     }) 
 
     .catch(err => console.log(err)); 
 
    }

Aber immer, wenn er die Daten empfangen werden, die render() Funktion bereits beendet ist, sollte ich es zwingen, wieder zu aktualisieren?

+0

Sie Rückkehr nichts von 'getData' Funktion, sondern auch dann, wenn Sie zurückkommen tun' result', das ist async so Sie werden 'result' nicht in' componentDidMount' sehen. –

+0

Ich habe das Problem verstanden, aber wann immer ich ein "Versprechen" zurücksende, wie sollte ich React informieren, um die 'render()' Funktionen zu aktualisieren. –

+0

Ein Artikel, der alle Fragen darüber beantwortet, wie, wann und wo man Daten in React abrufen kann: [Wie man Daten in React abruft] (https://www.robinwieruch.de/react-fetching-data/). Vielleicht hilft es den Leuten, etwas darüber zu erfahren, wenn sie über diese Frage stolpern. –

Antwort

1

Sie sollten nicht versuchen, das Rendering und/oder das Mounten der Komponente zu verzögern, bis Sie eine Antwort erhalten. Stattdessen sollten Sie Callbacks verwenden, um sicherzustellen, dass alles nach Wunsch aktualisiert wird, sobald die Anfrage beendet ist.

Sie müssen nur den Code für getData ändern, sodass ein Rückruf ausgeführt wird, sobald die Anforderung beendet ist. Sie haben hier zwei Möglichkeiten.

  1. Machen Sie die getData Funktion einen dritten Parameter callback und rufen Sie diese Methode akzeptieren, wenn Sie die Antwort handhaben. Dies würde aussehen grob wie folgt aus:

let getData = (dataURL, headers, callback) => { 
    let result = { 
    data: [], 
    message: '' 
    }; 
    if (dataURL === null || dataURL === undefined || dataURL === '') { 
    result.message = 'URL is not correct'; 
    responseData(result); 
    } 
    fetch(dataURL, headers) 
    .then(response =>{ 
     if (response.ok) { 
     response.json().then(data => { 
      result.data = data; 
      result.message = response.statusText; 
      responseData(result); 
     }); 
     }else{ 
     result.message = 'Network response was not ok.'; 
     responseData(result); 
     } 
     callback(result); 
    }) 
    .catch(err => console.log(err)); 
}; 

Denken Sie daran, dass dies nicht wie eine tatsächliche Umsetzung aussehen würde. Im Falle einer Ausnahme würde der Callback nicht aufgerufen werden und der aufrufende Code würde niemals wissen, was passiert ist. Aber im Grunde würde es so funktionieren.

  1. Machen Sie die getData Funktion das Versprechen durch die fetch API erstellt zurückzukehren. Dies ist diejenige, die ich persönlich verwenden würde, weil sie sauberer aussieht und ich an jedem Wochentag Promises über Callbacks ergreife.

let getData = (dataURL, headers) => { 
    let result = { 
    data: [], 
    message: '' 
    }; 
    if (dataURL === null || dataURL === undefined || dataURL === '') { 
    result.message = 'URL is not correct'; 
    responseData(result); 
    } 
    return fetch(dataURL, headers) 
    .then(response =>{ 
     if (response.ok) { 
     response.json().then(data => { 
      result.data = data; 
      result.message = response.statusText; 
      responseData(result); 
     }); 
     }else{ 
     result.message = 'Network response was not ok.'; 
     responseData(result); 
     } 
     return result; 
    }) 
    .catch(err => console.log(err)); 
}; 

Hinzufügen Genau das return Schlüsselwort das Versprechen zurückkehren würde und dann würden Sie den Wunsch Ihres Herzens zu Kettenlader können.

OK, wie nutzen wir das? Es ist eigentlich ziemlich einfach. Sie haben jetzt die Möglichkeit, der getData-Methode zu sagen, etwas zu tun, sobald eine Antwort empfangen wurde (oder eine Ausnahme ausgelöst wurde).

Nur als Beispiel können Sie dies in der componentWillMount Methode Ihrer React-Komponente tun.

componentWillMount() { 
    getData('http://example.com', new Headers()) 
     .then(function(result) { 
      this.setState({ items: result }); 
     }); 
} 

Sie können auch die Ladeplatte steuern, indem ein Flag in dem Zustand vor der Anforderung einstellen, und es nach der Anfrage (mit Rückrufe natürlich) zurückgesetzt wird.

+0

Wenn ich den Abruf nicht direkt zurücksende, erhalte ich immer ein leeres Objekt oder 'undefined', gibt es eine Möglichkeit, in diesem Fall eine' Versprechung' zurückzugeben? –

2

result ist nicht die Daten, es ist ein Versprechen, mit dem Sie auf die Daten zugreifen können. Sie müssen das Promise von fetch zurückgeben und müssen auch die Daten von Ihrem then innerhalb getData zurückgeben und Ihren React-Code aktualisieren.

getData Änderung

return fetch(dataURL, headers) 
    .then(response =>{ 
    if (response.ok) { 
     response.json().then(data => { 
     result.data = data; 
     result.message = response.statusText; 
     return responseData(result); 
     }); 
    } else { 
     result.message = 'Network response was not ok.'; 
     return responseData(result); 
    } 
    }) 
    .catch(err => console.log(err)); 

Reagieren Änderung

componentDidMount() { 
    var self = this; 
    let result = util.getData('http://localhost:3001/menus'); 
    const { dispatch } = this.props; 
    // dispatch(menuActions.fetchMenusIfNeeded()); 
    result.then((data) => { 
     if (this.isMounted()) { 
     this.setState({ 
      items: data.results 
     }); 
     } 
    }); 
} 
+0

danke für deine Antwort, ich habe versucht, 'then()' für das 'result' zu setzen, aber das' result' ist immer 'undefined', sollte ich versuchen, das Ergebnis direkt von 'fetch' zurückzugeben? –

+0

Könnten Sie sich meinen bearbeiteten Funktionsaufruf ansehen? Wie sollte ich React wissen lassen über die Daten und aktualisieren Sie die render() –

+0

Zwei Gedanken, sind Sie sicher, dass diese Bedingung wahr ist ?: 'if (response.ok) {', so oder so, ich denke, das Problem könnte sein, dass Sie initialisiere deinen Zustand mit: 'data: []' aber du stellst das Ergebnis auf 'items:' ein. Sie müssen wahrscheinlich auf: 'this.setState ({data: data.results})' aktualisieren, vorausgesetzt, Ihre Renderfunktion arbeitet mit 'data' und nicht mit' items' –