One place for hosting & domains

      Thunk

      Memahami Aksi Redux Asinkron dengan Redux Thunk


      Pengantar

      Secara asali, aksi Redux dikirimkan secara sinkron, yang menjadi masalah bagi aplikasi nontrivial yang perlu berkomunikasi dengan API eksternal atau melakukan efek samping. Redux juga memungkinkan pengiriman middleware yang berada di antara aksi dan aksi mencapai reducer.

      Ada dua pustaka middleware yang sangat populer yang memungkinkan efek samping dan akses asinkron: Redux Thunk dan Redux Saga. Dalam artikel ini, Anda akan mendalami Redux Thunk.

      Thunk adalah konsep pemrograman yang menggunakan fungsi untuk menunda evaluasi/kalkulasi suatu operasi.

      Redux Thunk adalah middleware yang memungkinkan Anda memanggil pembuat aksi yang mengembalikan fungsi sebagai ganti objek aksi. Fungsi itu menerima metode pengiriman penyimpanan, yang kemudian digunakan untuk mengirim aksi sinkron di dalam isi fungsi setelah operasi asinkron selesai.

      Dalam artikel ini, Anda akan mempelajari cara menambahkan Redux Thunk dan membuatnya cocok dengan aplikasi Todo hipotetis.

      Prasyarat

      Artikel ini beranggapan Anda telah memiliki sejumlah pengetahuan dasar tentang React dan Redux. Anda dapat merujuk artikel ini jika sudah mulai menggunakan Redux.

      Tutorial ini membangun dari aplikasi Todo hipotetis yang melacak berbagai tugas yang perlu dilakukan dan yang telah selesai. Kita dapat menganggap bahwa create-react-app telah digunakan untuk membuat aplikasi React baru, serta redux, react-redux, dan axios telah terinstal.

      Detail lebih akurat tentang cara membangun aplikasi Todo dari awal tidak dijelaskan di sini. Artikel ini disajikan sebagai pengaturan konseptual untuk menyoroti Redux Thunk.

      Menambahkan redux-thunk

      Pertama, gunakan terminal untuk menavigasi ke direktori proyek dan instal paket redux-thunk di proyek Anda:

      • npm install redux-thunk@2.3.0

      Catatan: Kode Redux Thunk hanya 14 baris. Lihatlah sumbernya di sini untuk mempelajari cara kerja middleware Redux di balik layar.

      Sekarang, terapkan middleware saat membuat penyimpanan aplikasi menggunakan applyMiddleware Redux. Dengan anggapan aplikasi React berisi redux dan react-redux, berkas index.js Anda mungkin terlihat seperti ini:

      src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import './index.css';
      import rootReducer from './reducers';
      import App from './App';
      import * as serviceWorker from './serviceWorker';
      
      // use applyMiddleware to add the thunk middleware to the store
      const store = createStore(rootReducer, applyMiddleware(thunk));
      
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
      

      Sekarang, Redux Thunk diimpor dan diterapkan di aplikasi Anda.

      Menggunakan Thunk Redux di Aplikasi Sampel

      Kasus penggunaan paling umum untuk Redux Thunk adalah berkomunikasi secara asinkron dengan API eksternal untuk mengambil atau menyimpan data. Redux Thunk memudahkan pengiriman aksi yang mengikuti siklus hidup permintaan ke API eksternal.

      Membuat item agenda baru biasanya melibatkan pengiriman aksi terlebih dahulu untuk mengindikasikan bahwa pembuatan item agenda telah dimulai. Kemudian, jika item agenda berhasil dibuat dan dikembalikan oleh server eksternal, aksi lain akan dikirim bersama item agenda baru. Jika ada kesalahan dan agenda gagal disimpan di server, sebuah aksi bersama kesalahan dapat dikirim sebagai gantinya.

      Mari kita lihat cara melakukannya menggunakan Redux Thunk.

      Dalam komponen kontainer Anda, impor aksi dan kirimkan:

      src/containers/AddTodo.js

      import { connect } from 'react-redux';
      import { addTodo } from '../actions';
      import NewTodo from '../components/NewTodo';
      
      const mapDispatchToProps = dispatch => {
        return {
          onAddTodo: todo => {
            dispatch(addTodo(todo));
          }
        };
      };
      
      export default connect(
        null,
        mapDispatchToProps
      )(NewTodo);
      

      Aksi ini akan menggunakan Axios untuk mengirim permintaan POST ke titik akhir di JSONPlaceholder (https://jsonplaceholder.typicode.com/todos):

      src/actions/index.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from './types';
      
      import axios from 'axios';
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(`https://jsonplaceholder.typicode.com/todos`, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      const addTodoSuccess = todo => ({
        type: ADD_TODO_SUCCESS,
        payload: {
          ...todo
        }
      });
      
      const addTodoStarted = () => ({
        type: ADD_TODO_STARTED
      });
      
      const addTodoFailure = error => ({
        type: ADD_TODO_FAILURE,
        payload: {
          error
        }
      });
      

      Perhatikan cara pembuat aksi addTodo mengembalikan fungsi sebagai ganti objek aksi reguler. Fungsi itu menerima metode pengiriman dari penyimpanan.

      Di dalam isi fungsi, Anda mengirim aksi sinkron segera ke penyimpanan terlebih dahulu untuk mengindikasikan bahwa Anda telah mulai menyimpan agenda bersama API eksternal. Kemudian, Anda membuat permintaan POST sesungguhnya ke server menggunakan Axios. Pada respons yang berhasil dari server, Anda mengirim aksi sinkron yang berhasil bersama data yang diterima dari respons tersebut, tetapi bila respons gagal, kita mengirim tindakan sinkron yang berbeda bersama pesan kesalahan.

      Saat menggunakan API yang bersifat eksternal, seperti JSONPlaceholder dalam kasus ini, kita bisa melihat penundaan jaringan yang terjadi sesungguhnya. Namun, jika Anda menggunakan server backend lokal, respons jaringan mungkin menjadi terlalu cepat mengalami penundaan jaringan yang nanti dialami pengguna sesungguhnya, sehingga Anda dapat menambahkan penundaan buatan saat pengembangan:

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              setTimeout(() => {
                dispatch(addTodoSuccess(res.data));
              }, 2500);
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Untuk menguji skenario kesalahan, Anda dapat melontarkan kesalahan secara manual:

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              throw new Error('addToDo error!');
              // dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Untuk kelengkapan, inilah contoh bentuk reducer agenda untuk menangani siklus hidup penuh dari permintaan:

      src/reducers/todosReducer.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from '../actions/types';
      
      const initialState = {
        loading: false,
        todos: [],
        error: null
      };
      
      export default function todosReducer(state = initialState, action) {
        switch (action.type) {
          case ADD_TODO_STARTED:
            return {
              ...state,
              loading: true
            };
          case ADD_TODO_SUCCESS:
            return {
              ...state,
              loading: false,
              error: null,
              todos: [...state.todos, action.payload]
            };
          case ADD_TODO_FAILURE:
            return {
              ...state,
              loading: false,
              error: action.payload.error
            };
          default:
            return state;
        }
      }
      

      Mendalami getState

      Selain menerima metode pengiriman dari status, fungsi yang dikembalikan oleh pembuat aksi asinkron bersama Redux Thunk juga menerima metode getState dari penyimpanan, sehingga nilai-nilai penyimpanan saat ini dapat dibaca:

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          dispatch(addTodoStarted());
      
          console.log('current state:', getState());
      
          // ...
        };
      };
      

      Dengan hal tersebut di atas, status saat ini akan dicetak ke konsol saja.

      Misalnya:

      {loading: true, todos: Array(1), error: null}
      

      Penggunaan getState dapat digunakan untuk menangani hal-hal berbeda, bergantung pada status saat ini. Misalnya, jika ingin membatasi aplikasi pada empat item agenda saja untuk setiap kalinya, Anda dapat kembali dari fungsi jika status sudah berisi item agenda dalam jumlah maksimum:

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          const { todos } = getState();
      
          if (todos.length > 4) return;
      
          dispatch(addTodoStarted());
      
          // ...
        };
      };
      

      Dengan hal tersebut di atas, aplikasi akan dibatasi pada empat item agenda.

      Kesimpulan

      Dalam tutorial ini, Anda telah mendalami penambahan Redux Thunk ke aplikasi React untuk memungkinkan pengiriman aksi secara asinkron. Hal ini berguna saat memanfaatkan penyimpanan Redux dan mengandalkan API eksternal.

      Jika Anda ingin mempelajari lebih lanjut tentang React, lihat seri Cara Melakukan Pengodean di React.js dari kami, atau baca halaman topik React kami untuk proyek pemrograman dan latihan.



      Source link

      Comprendre les actions asynchrones de Redux avec Redux Thunk


      Introduction

      Par défaut, les actions de Redux sont expédiées de façon synchrone, ce qui pose un problème pour toute application non triviale qui doit communiquer avec une application externe ou effectuer des effets secondaires. Redux permet également au middleware qui se trouve au milieu d’une action d’être distribué et à l’action d’atteindre les réducteurs.

      Il existe deux bibliothèques de middleware très populaires qui prennent en charge les effets spéciaux et les actions asynchrones : Redux Thunk et Redux Saga. Cette publication vous emmène à la découverte de Redux Thunk.

      Thunk est un concept de programmation dans lequel une fonction est utilisée pour retarder l’évaluation/le calcul d’une opération.

      Redux Thunk est un middleware qui vous permet de faire un appel à l’action auprès des créateurs qui renvoie une fonction au lieu d’un objet d’action. Cette fonction reçoit la méthode de distribution du store. Elle permet donc d’envoyer des actions synchrones régulières dans le corps de la fonction une fois que les opérations asynchrones ont été terminées.

      Dans cet article vous allez apprendre à ajouter Redux Thunk et découvrir de quelle manière il peut s’adapter à une application hypothétique de Todo.

      Conditions préalables

      Cet article suppose que vous disposez de certaines connaissances de base sur React et Redux. Vous pouvez consulter cet article si vous débutez avec Redux.

      Ce tutoriel est construit autour d’une hypothétique application de Todo qui est supposée assurer le suivi des tâches à faire et des tâches accomplies. Nous présumons que create-react-app a été utilisée pour générer une nouvelle application React. Cependant, redux, react-redux et axios ont déjà été installés.

      Cet article ne vous donne pas d’informations plus détaillées sur la manière de créer une application de Todo de zéro. Nous la présentons ici comme un paramètre conceptuel pour mettre en avant Redux Thunk.

      Ajout de redux-thunk

      Tout d’abord, utilisez le terminal pour naviguer vers le répertoire de projets et installez le paquet redux-thunk dans votre projet :

      • npm install redux-thunk@2.3.0

      Remarque : Redux Thunk ne dispose que de 14 lignes de code. Consultez la source ici pour en savoir plus sur le fonctionnement en arrière-plan d’un middleware Redux.

      Maintenant, utilisez le middleware pour créer le store de votre application en utilisant applyMiddleware de Redux. Avec une application React intégrant redux et react-redux, votre fichier index.js devrait ressembler à ce qui suit :

      src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import './index.css';
      import rootReducer from './reducers';
      import App from './App';
      import * as serviceWorker from './serviceWorker';
      
      // use applyMiddleware to add the thunk middleware to the store
      const store = createStore(rootReducer, applyMiddleware(thunk));
      
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
      

      Maintenant, Redux Thunk a été importé et appliqué dans votre application.

      Utilisation de Redux Thunk dans un exemple d’application

      Redux Thunk est le plus couramment utilisé pour communiquer de manière asynchrone avec une application externe afin de récupérer ou de sauvegarder des données. Redux Thunk vous permet de facilement distribuer des actions qui suivent le cycle de vie d’une requête à une application externe.

      En règle générale, pour créer un nouvel élément de todo, il faut lancer une action pour indiquer qu’une création d’un élément todo a commencé. Ensuite, si l’élément todo est bien créé et renvoyé par le serveur externe, une autre action est distribuée avec le nouvel élément todo. Si une erreur survient et le serveur ne sauvegarde pas le todo, une action accompagnée d’une erreur risque d’être déclenchée.

      Voyons comment nous pourrions le faire avec Redux Thunk.

      Importez et distribuez l’action dans votre composant de conteneur :

      src/containers/AddTodo.js

      import { connect } from 'react-redux';
      import { addTodo } from '../actions';
      import NewTodo from '../components/NewTodo';
      
      const mapDispatchToProps = dispatch => {
        return {
          onAddTodo: todo => {
            dispatch(addTodo(todo));
          }
        };
      };
      
      export default connect(
        null,
        mapDispatchToProps
      )(NewTodo);
      

      L’action utilisera Axios pour envoyer une requête POST au terminal, au niveau de JSONPlaceholder (https://jsonplaceholder.typicode.com/todos) :

      src/actions/index.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from './types';
      
      import axios from 'axios';
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(`https://jsonplaceholder.typicode.com/todos`, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      const addTodoSuccess = todo => ({
        type: ADD_TODO_SUCCESS,
        payload: {
          ...todo
        }
      });
      
      const addTodoStarted = () => ({
        type: ADD_TODO_STARTED
      });
      
      const addTodoFailure = error => ({
        type: ADD_TODO_FAILURE,
        payload: {
          error
        }
      });
      

      Notez que le créateur d’action addTodo renvoie une fonction au lieu de l’objet d’action habituel. Cette fonction reçoit la méthode d’envoi du store.

      À l’intérieur du corps de la fonction, envoyez tout d’abord une action synchrone immédiate au store pour indiquer que vous avez commencé à enregistrer le todo avec l’application externe. Ensuite, vous devez envoyer la requête POST en elle-même au serveur, en utilisant Axios. Si le serveur vous envoie une réponse positive, vous distribuez une action synchrone probante avec les données reçues via la réponse. Mais, si la réponse est un échec, nous distribuons une action synchrone différente avec le message d’erreur.

      Lorsque vous utilisez une API externe, comme JSONPlaceholder dans le cas présent, il est possible qu’il y ait un retard au niveau du réseau. Cependant, si vous travaillez avec un serveur de backend local, il se peut que les réponses du réseau soient trop rapides pour pouvoir constater le retard de réseau qu’un utilisateur réel devrait subir. Vous pouvez donc ajouter un retard artificiel au cours du développement :

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              setTimeout(() => {
                dispatch(addTodoSuccess(res.data));
              }, 2500);
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Pour tester les scénarios d’erreur, vous pouvez lancer une erreur manuellement :

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              throw new Error('addToDo error!');
              // dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Pour compléter, voici un exemple de ce à quoi le réducteur de todo pourrait ressembler pour prendre en charge l’intégralité du cycle de vie de la requête :

      src/reducers/todosReducer.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from '../actions/types';
      
      const initialState = {
        loading: false,
        todos: [],
        error: null
      };
      
      export default function todosReducer(state = initialState, action) {
        switch (action.type) {
          case ADD_TODO_STARTED:
            return {
              ...state,
              loading: true
            };
          case ADD_TODO_SUCCESS:
            return {
              ...state,
              loading: false,
              error: null,
              todos: [...state.todos, action.payload]
            };
          case ADD_TODO_FAILURE:
            return {
              ...state,
              loading: false,
              error: action.payload.error
            };
          default:
            return state;
        }
      }
      

      Découverte de getState

      Non seulement la méthode de distribution de l’état est reçue, mais la fonction renvoyée par un créateur d’action asynchrone avec Redux Thunk reçoit également la méthode getState du store pour pouvoir lire les valeurs réelles du store :

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          dispatch(addTodoStarted());
      
          console.log('current state:', getState());
      
          // ...
        };
      };
      

      Avec ce qui précède, l’état actuel s’imprimera sur la console.

      Par exemple :

      {loading: true, todos: Array(1), error: null}
      

      Il peut s’avérer utile d’utiliser getState pour gérer les choses différemment en fonction de l’état actuel. Par exemple, si vous souhaitez limiter l’application à quatre éléments de todo à la fois, vous pouvez les renvoyer à partir de la fonction, si l’état contient déjà le nombre maximum d’éléments todo :

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          const { todos } = getState();
      
          if (todos.length > 4) return;
      
          dispatch(addTodoStarted());
      
          // ...
        };
      };
      

      Compte tenu de ce qui précède, l’app sera limitée à quatre éléments de todo.

      Conclusion

      Au cours de ce tutoriel, vous avez appris à ajouter Redux Thunk à une application React pour pouvoir exécuter des actions de manière asynchrone. Ceci est utile si vous utilisez un store Redux et que vous vous appuyez sur des API externes.

      Si vous souhaitez en savoir plus sur React, consultez notre série Comment coder dans React.js ou consultez notre page thématique React pour des exercices et des projets de programmation.



      Source link

      Grundlegendes zu asynchronen Redux-Aktionen mit Redux Thunk.


      Einführung

      Standardmäßig werden die Aktionen von Redux synchron versendet, was ein Problem für jede nicht-triviale Anwendung ist, die mit einer externen API kommunizieren muss oder Nebenwirkungen ausführt. Redux ermöglicht auch Middleware, die zwischen dem Versand einer Aktion und dem Eintreffen der Aktion bei den Reduzierern angesiedelt ist.

      Es gibt zwei sehr beliebte Middleware-Bibliotheken, die Nebenwirkungen und asynchrone Aktionen ermöglichen: Redux Thunk und Redux Saga. In diesem Beitrag erkunden Sie Redux Thunk.

      Thunk ist ein Programmierkonzept, bei dem eine Funktion verwendet wird, um die Bewertung/Berechnung einer Aktion zu verzögern.

      Redux Thunk ist eine Middleware, mit der Sie Aktionserzeuger aufrufen können, die anstelle eines Aktionsobjekts eine Funktion zurückgeben.  Diese Funktion empfängt die Versandmethode des Speichers, die dann verwendet wird, um regelmäßige synchrone Aktionen innerhalb des Funktionskörpers zu versenden, sobald die asynchronen Operationen abgeschlossen sind.

      In diesem Artikel lernen Sie, wie Sie Redux Thunk hinzufügen und wie es in eine hypothetischen Todo-Anwendung passen kann.

      Voraussetzungen

      Dieser Beitrag geht davon aus, dass Sie einige grundlegende Kenntnisse von React und Redux haben. Wenn Sie mit Redux beginnen, können Sie auf diesen Beitrag verweisen.

      Dieses Tutorial baut auf einer hypothetischen Todo-Anwendung auf, die zu erledigende und abgeschlossene Tasks verfolgt.  Wir gehen davon aus, dass create-react-app verwendet wurde, um eine neue React-Anwendung zu generieren, und redux, react-redux und axios bereits installiert sind.

      Die genaueren Details, wie man eine Todo-Anwendung von Grund auf neu erstellt, werden hier nicht erläutert. Es wird als konzeptioneller Rahmen für die Hervorhebung von Redux Thunk präsentiert.

      Hinzufügen von redux-thunk

      Verwenden Sie zunächst das Terminal, um zum Projektverzeichnis zu navigieren und das redux-thunk Paket in Ihrem Projekt zu installieren:

      • npm install redux-thunk@2.3.0

      Anmerkung: Redux Thunk besteht nur aus 14 Zeilen Code. Sehen Sie sich die Quelle hier an, um zu erfahren, wie eine Redux Middleware unter der Oberfläche funktioniert.

      Verwenden Sie nun die Middleware bei der Erstellung Ihres App-Stores mit der Anwendung von Redux applyMiddleware. Angesichts einer React-Anwendung mit redux und react-redux sieht Ihre Datei index.js wie folgt aus:

      src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import './index.css';
      import rootReducer from './reducers';
      import App from './App';
      import * as serviceWorker from './serviceWorker';
      
      // use applyMiddleware to add the thunk middleware to the store
      const store = createStore(rootReducer, applyMiddleware(thunk));
      
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
      

      Jetzt wird Redux Thunk in Ihre Anwendung importiert und angewendet.

      Verwenden von Redux Thunk in einer Beispielanwendung

      Der häufigste Anwendungsfall für Redux Thunk ist die asynchrone Kommunikation mit einer externen API zum Abrufen oder Speichern von Daten. Mit Redux Thunk ist es einfach, Aktionen, die dem Lebenszyklus einer Anforderung folgen, an eine externe API zu senden.

      Bei der Erstellung eines neuen ToDo-Elements wird normalerweise zuerst eine Aktion gesendet, um anzuzeigen, dass die Erstellung eines ToDo-Elements begonnen hat.  Wenn dann das ToDo-Element erfolgreich erstellt und vom externen Server zurückgegeben wird, senden Sie eine weitere Aktion mit dem neuen ToDo-Element. Für den Fall, dass ein Fehler auftritt und das ToDo nicht auf dem Server gespeichert werden kann, kann stattdessen eine Aktion mit dem Fehler versendet werden.

      Sehen wir uns an, wie dies mit Redux Thunk erreicht werden kann.

      Importieren Sie in Ihrer Container-Komponente die Aktion und versenden Sie diese:

      src/containers/AddTodo.js

      import { connect } from 'react-redux';
      import { addTodo } from '../actions';
      import NewTodo from '../components/NewTodo';
      
      const mapDispatchToProps = dispatch => {
        return {
          onAddTodo: todo => {
            dispatch(addTodo(todo));
          }
        };
      };
      
      export default connect(
        null,
        mapDispatchToProps
      )(NewTodo);
      

      Die Aktion verwendet Axios um eine POST-Anfrage an den Endpunkt bei JSONPlaceholder zu senden (https://jsonplaceholder.typicode.com/todos):

      src/actions/index.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from './types';
      
      import axios from 'axios';
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(`https://jsonplaceholder.typicode.com/todos`, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      const addTodoSuccess = todo => ({
        type: ADD_TODO_SUCCESS,
        payload: {
          ...todo
        }
      });
      
      const addTodoStarted = () => ({
        type: ADD_TODO_STARTED
      });
      
      const addTodoFailure = error => ({
        type: ADD_TODO_FAILURE,
        payload: {
          error
        }
      });
      

      Beachten Sie, wie der AddTodo-Aktionserzeuger anstelle des regulären Aktionsobjekts eine Funktion zurückgibt. Diese Funktion empfängt die Versandmethode aus dem Store.

      Innerhalb des Funktionskörpers versenden Sie zunächst eine sofortige synchrone Aktion an den Store, um anzuzeigen, dass Sie begonnen haben, das Todo mit der externen API zu speichern. Dann stellen Sie die aktuelle POST-Anfrage mit Axios an den Server her. Bei einer erfolgreichen Antwort vom Server senden Sie eine synchrone Erfolgsaktion mit den von der Antwort empfangenen Daten, bei einer fehlgeschlagenen Antwort senden wir jedoch eine andere synchrone Aktion mit der Fehlermeldung.

      Bei Verwendung einer externen API, wie in diesem Fall JSONPlaceholder, ist es möglich, die tatsächliche Netzwerkverzögerung zu sehen. Wenn Sie jedoch mit einem lokalen Backend-Server arbeiten, kann es vorkommen, dass die Netzwerkreaktionen zu schnell erfolgen, um die Netzwerkverzögerung zu erfassen, die ein tatsächlicher Benutzer erfahren würde, so dass Sie bei der Entwicklung eine künstliche Verzögerung hinzufügen können:

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              setTimeout(() => {
                dispatch(addTodoSuccess(res.data));
              }, 2500);
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Um Fehlerszenarien auszuprobieren, können Sie einen Fehler manuell einwerfen:

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              throw new Error('addToDo error!');
              // dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Der Vollständigkeit halber hier ein Beispiel dafür, wie der Todo-Reducer aussehen könnte, um den gesamten Lebenszyklus der Anfrage zu bewältigen:

      src/reducers/todosReducer.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from '../actions/types';
      
      const initialState = {
        loading: false,
        todos: [],
        error: null
      };
      
      export default function todosReducer(state = initialState, action) {
        switch (action.type) {
          case ADD_TODO_STARTED:
            return {
              ...state,
              loading: true
            };
          case ADD_TODO_SUCCESS:
            return {
              ...state,
              loading: false,
              error: null,
              todos: [...state.todos, action.payload]
            };
          case ADD_TODO_FAILURE:
            return {
              ...state,
              loading: false,
              error: action.payload.error
            };
          default:
            return state;
        }
      }
      

      Erkunden von getState

      Neben dem Empfangen der Versandmethode aus dem Zustand empfängt die von einem asynchronen Aktionserzeuger mit Redux Thunk zurückgegebene Funktion auch die getState Methode des Stores so, dass aktuelle Speicherwerte gelesen werden können:

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          dispatch(addTodoStarted());
      
          console.log('current state:', getState());
      
          // ...
        };
      };
      

      Damit wird der aktuelle Zustand einfach auf die Konsole ausgedruckt.

      Beispiel:

      {loading: true, todos: Array(1), error: null}
      

      Die Verwendung von getState kann nützlich sein, die Dinge je nach aktuellen Zustand unterschiedlich zu handhaben.  Wenn Sie beispielsweise die Anwendung auf nur vier ToDo-Einträge auf einmal beschränken möchten, können Sie von der Funktion zurückkehren, wenn der Status bereits die maximale Anzahl an ToDo-Einträgen enthält:

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          const { todos } = getState();
      
          if (todos.length > 4) return;
      
          dispatch(addTodoStarted());
      
          // ...
        };
      };
      

      Damit wird die Anwendung auf vier ToDo-Einträge beschränkt.

      Zusammenfassung

      In diesem Tutorial haben Sie das Hinzufügen von Redux Thunk zu einer React-Anwendung untersucht, um das asynchrone Zuweisen von Aktionen zu ermöglichen. Dies ist nützlich, wenn ein Redux-Speicher verwendet wird und man sich auf externe APIs verlässt.

      Wenn Sie mehr über React erfahren möchten, sehen Sie sich unsere Reihe Codieren in React.js an oder besuchen Sie unsere React-Themenseite für Übungen und Programmierprojekte.



      Source link