React-Redux: Aktionen müssen einfache Objekte sein. Verwenden Sie benutzerdefinierte Middleware für asynchrone Aktionen


76

Nicht behandelte Ablehnung (Fehler): Aktionen müssen einfache Objekte sein. Verwenden Sie benutzerdefinierte Middleware für asynchrone Aktionen.

Ich wollte mit jedem Beitrag Kommentare hinzufügen. Wenn Abrufbeiträge ausgeführt werden, möchte ich die Abrufkommentar-API für alle Beiträge aufrufen.

export function bindComments(postId) {
  return API.fetchComments(postId).then(comments => {
    return {
      type: BIND_COMMENTS,
      comments,
      postId
    }
  })
}

Antworten:


60

Sie müssen nach Beendigung der asynchronen Anforderung versenden.

Das würde funktionieren:

export function bindComments(postId) {
    return function(dispatch) {
        return API.fetchComments(postId).then(comments => {
            // dispatch
            dispatch({
                type: BIND_COMMENTS,
                comments,
                postId
            });
        });
    };
}

4
Es wird unten erwähnt, aber Sie benötigen Redux-Thunk-Middleware, damit dies funktioniert
Charlie Stanard

1
@sadiq warum ist es obligatorisch, eine Aktion auszulösen? Ich hatte das gleiche Problem mit einer asynchronen Aktion, die ich nicht als "asynchroner Versand" definiert habe, obwohl ich nichts in den Laden versenden wollte.
Soragim

11

Sie können Fetch nicht in Aktionen ohne Middleware verwenden. Aktionen müssen einfache Objekte sein. Sie können eine Middleware wie Redux-Thunk oder Redux-Saga verwenden, um eine andere Aktion abzurufen und dann auszulösen.

Hier ist ein Beispiel für eine asynchrone Aktion mit Redux-Thunk-Middleware.

export function checkUserLoggedIn (authCode) {
 let url = `${loginUrl}validate?auth_code=${authCode}`;
  return dispatch => {
    return fetch(url,{
      method: 'GET',
      headers: {
        "Content-Type": "application/json"
      }
      }
    )
      .then((resp) => {
        let json = resp.json();
       if (resp.status >= 200 && resp.status < 300) {
          return json;
        } else {
          return json.then(Promise.reject.bind(Promise));
        }
      })
      .then(
        json => {
          if (json.result && (json.result.status === 'error')) {
            dispatch(errorOccurred(json.result));
            dispatch(logOut());
          }
          else{
            dispatch(verified(json.result));
          }
        }
      )
      .catch((error) => {
        dispatch(warningOccurred(error, url));
      })
  }
}

Entschuldigung, ich dachte, Sie verwenden keine Middleware. Es war ein Versandproblem, das @sadiq erwähnte.
Sinapcs

11

Für zukünftige Suchende, die möglicherweise einfache Details wie mich fallen gelassen haben, habe ich in meinem Fall einfach vergessen, meine Aktionsfunktion in Klammern aufzurufen.

action.js:

export function addNewComponent() {
  return {
    type: ADD_NEW_COMPONENT,
  };
}

myComponent.js:

import React, { useEffect } from 'react';
import { addNewComponent } from '../../redux/actions';

  useEffect(() => {
    dispatch(refreshAllComponents); // <= Here was what I've missed.
  }, []);

Ich habe vergessen, die Aktionsfunktion mit zu versenden (). Damit war mein Problem gelöst.

  useEffect(() => {
    dispatch(refreshAllComponents());
  }, []);

Auch dies hat vielleicht nichts mit dem Problem von OP zu tun, aber ich hoffe, ich helfe Menschen mit dem gleichen Problem wie ich.


1
Danke dafür. Leicht zu übersehen. Ich habe keine asynchronen Sachen gemacht, also wusste ich, dass es etwas Einfaches war, das ich verpasst habe!
Taylor A. Leach

6

Verwenden Sie die Pfeilfunktionen, um die Lesbarkeit des Codes zu verbessern. Sie müssen nichts zurückgeben API.fetchComments. Der Api-Aufruf ist asynchron, wenn die Anforderung abgeschlossen thenist. Sie erhalten die Antwort. Dort müssen Sie nur noch dispatcheingeben und Daten eingeben.

Der folgende Code erledigt den gleichen Job, indem er die Pfeilfunktionen verwendet.

export const bindComments = postId => {
  return dispatch => {
    API.fetchComments(postId).then(comments => {
      dispatch({
        type: BIND_COMMENTS,
        comments,
        postId
      });
    });
  };
};

3

Der Fehler besteht lediglich darin, dass Sie eine Middleware dazwischen einfügen müssen, um asynchrone Vorgänge zu handhaben.

Sie könnten das tun durch:

npm ich redux-thunk

        Inside index.js

import thunk from "redux-thunk" 
        
...createStore(rootReducers, applyMiddleware(thunk));

Jetzt funktionieren asynchrone Vorgänge in Ihren Funktionen.


2

Ich hatte das gleiche Problem, als ich das Hinzufügen von composeEnhancers verpasst hatte. Sobald dies eingerichtet ist, können Sie einen Blick auf die Ersteller von Aktionen werfen. Sie erhalten diesen Fehler, wenn dies nicht ebenfalls eingerichtet ist.

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  rootReducer,
  composeEnhancers(applyMiddleware(thunk))
);

0

Aktionsdefinition

const selectSlice = () => {
  return {
    type: 'SELECT_SLICE'
  }
};

Aktion Versand

store.dispatch({
  type:'SELECT_SLICE'
});

Stellen Sie sicher, dass die Objektstruktur der definierten Aktion mit der ausgelösten Aktion übereinstimmt. In meinem Fall wurde beim Versenden der Aktion der Eigenschaft kein Typ zugewiesen type.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.