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
    }
  })
}
Rajib Ahmed
quelle

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
            });
        });
    };
}
sadiq
quelle
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));
      })
  }
}
Sinapcs
quelle
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.

Alex Jolig
quelle
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
      });
    });
  };
};
Amruth LS
quelle
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.

Ashutosh Tiwari
quelle
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))
);
Sandeep Amarnath
quelle
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.

Yuvraj Patil
quelle