Ich habe Probleme mit dem Konzept von Promise in JavaScript. Ich schreibe eine React-App, die einen GET Aufruf an einen separaten API-Dienst in Java ausführt, und möchte dessen Status in einem useState() -Hook speichern. Hier ist mein fetch Code:

const ratingsUrl = "%URL%";
const base64 = require("base-64");
const login = "login";
const password = "password";

function fetchRatings() {
  return fetch(ratingsUrl, {
    method: "GET",
    headers: new Headers({
      Authorization: "Basic " + base64.encode(login + ":" + password),
    }),
  })
    .then((response) => response.json())
    .catch(handleError);
}

Und jetzt versuche ich, seinen Status in einem Hook in meiner Seitenkomponente zu speichern:

function DisplayPage(){
  const [ratings, setRatings] = useState(fetchRatings());

.
.
.
}

Jetzt kehren die Daten zurück, befinden sich jedoch in einem Promise, was später zu Fehlern führt:

Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(20)

Was ich tun muss, ist, die Daten in einem Hook zu initialisieren und in einem Table zurückzugeben, damit ich sie abbilden kann. Wenn ich jedoch versuche, so etwas zu tun

ratings.map()

Ich erhalte einen TypeError in der Konsole mit der Aufschrift ratings.Map is not a function.

Ich bin mir bewusst, dass die fetch - Bibliothek Daten asynchron zurückgibt, aber alles, was ich wirklich möchte, ist, dass die PromiseResult in einem useState() - Hook gespeichert wird, damit ich weiter unten Operationen ausführen kann Linie.

0
clattenburg cake 30 Sept. 2020 im 10:36

4 Antworten

Beste Antwort

async Methoden geben Versprechen zurück. Wenn Sie das Ergebnis eines Versprechens direkt in Ihrer Statusvariablen setRatings festlegen, erhalten Sie ein Versprechen.

Normalerweise wird dies wie folgt umgeschrieben:

function DisplayPage(){
  const [ratings, setRatings] = useState(null);

  useEffect(() => {

    fetchRatings
      .then(result => setRatings(result))
      .catch(err => console.error(err));

  }, []);
 
  if (ratings === null) return <div>loading...</div>;
  
  /* .. do your thing .. */

}
1
Evert 30 Sept. 2020 im 07:45

Wie wäre es damit ,

const [ratings, setRatings] =  useState();
useEffect(()=>{
         fetch(ratingsUrl, {
method: "GET",
headers: new Headers({
  Authorization: "Basic " + base64.encode(login + ":" + password),
})}).then((response) => {let res = response.json();
    setRatings(res)
      })
.catch(handleError);
 },[])
0
Arjun Biju 30 Sept. 2020 im 07:45

Ich würde empfehlen, den useEffect-Hook zu verwenden, um den Anfangszustand festzulegen (ähnlich wie componentDidMount).

Wenn die erwartete Antwort beispielsweise ein Array ist.

const [ratings, setRatings] = useState([]);

Aktualisieren Sie dann im useEffect-Hook den Status, wenn Sie eine Antwort von Ihrer Abrufanforderung erhalten. Auf diese Weise können Sie Fehler vermeiden, wenn Sie beispielsweise Bewertungen in Ihrem DOM irgendwo zuordnen, bevor die Anforderung abgeschlossen ist.

useEffect(){
    fetch(ratingsUrl, {
        method: "GET",
        headers: new Headers({
            Authorization: "Basic " + base64.encode(login + ":" + password),
        }),
    })
    .then((response) => {
         response.json()
    })
    .then(res => setRatings(res))
    .catch(handleError);
0
Yannick Vermeulen 30 Sept. 2020 im 07:48

Da der Abruf asynchron ausgeführt wird, können Sie Ihren Status nicht mit dem unmittelbaren Ergebnis des Aufrufs von fetchRatings initialisieren.

Glücklicherweise gibt es ein paar ziemlich einfache Möglichkeiten, damit umzugehen. Sie können Ihren Status mit einem leeren Wert initialisieren und dann aktualisieren, sobald fetchResults behoben ist:

function DisplayPage() {
  // initially ratings will be undefined
  const [ratings, setRatings] = useState();

  // update state when fetchResults comes back
  fetchResults().then(response => setRatings(response));

  // ...

Im obigen Beispiel wird dies aus Gründen der Lesbarkeit weggelassen. Dies geschieht jedoch im Allgemeinen über useEffect wird also ausgeführt, wenn Ihre Komponente bereitgestellt wird oder wenn sich relevante Eingaben (normalerweise Requisiten, sogenannte Abhängigkeiten für den Effekt) ändern:

function DisplayPage() {
  const [ratings, setRatings] = useState();

  useEffect(() => {
    fetchResults().then(response => setRatings(response));
  }, []) // empty dependencies array will cause the effect to run only once, on mount

  // ...
0
ray hatfield 30 Sept. 2020 im 07:55