Secara default, tindakan di Redux bersifat sinkron, yang merupakan masalah bagi aplikasi yang perlu berinteraksi dengan API server, atau melakukan tindakan asinkron lainnya. Untungnya, Redux memberi kita hal seperti middleware , yang berdiri di antara pengiriman aksi dan peredam. Ada dua perpustakaan middleware paling populer untuk tindakan asinkron di Redux, yaitu Redux Thunk dan Redux Saga . Dalam posting ini kita akan mempertimbangkan yang pertama.Redux Thunk adalah pustaka middleware yang memungkinkan Anda memanggil pembuat tindakan, mengembalikan fungsi alih-alih objek. Fungsi tersebut menggunakan metode pengiriman sebagai argumen, sehingga setelah operasi asinkron selesai, gunakan untuk mengirim tindakan sinkron biasa di dalam tubuh fungsi.
Jika Anda tertarik, maka Thunk adalah sebuah konsep dalam dunia pemrograman ketika suatu fungsi digunakan untuk menunda operasi.Instalasi dan pengaturan
Pertama, tambahkan paket
redux-thunk ke proyek Anda:
$ yarn add redux-thunk
Kemudian, tambahkan middleware ketika Anda membuat
toko aplikasi Anda menggunakan
applyMiddleware yang disediakan oleh Redux:
index.js import React from 'react'; import ReactDOM from 'react-dom'; import { createStore, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; import App from './App';
Penggunaan utama
Biasanya, Redux-Thunk digunakan untuk permintaan asinkron ke API eksternal, untuk mengambil atau menyimpan data. Redux-Thunk memudahkan pengiriman tindakan yang mengikuti "siklus hidup" permintaan API eksternal.
Misalnya, kami memiliki aplikasi todo reguler. Ketika kami mengklik "tambahkan todo", biasanya, tindakan pertama akan dikirim, yang melaporkan tentang awal menambahkan todo baru. Kemudian, jika elemen todo berhasil dibuat dan dikembalikan oleh server, tindakan lain dikirim dengan elemen todo baru kami, dan operasi berhasil. Jika karena alasan tertentu server mengembalikan kesalahan, alih-alih menambahkan todo baru, tindakan dengan kesalahan ditampilkan bahwa operasi belum selesai.
Mari kita lihat bagaimana ini dapat diimplementasikan menggunakan Redux-Thunk. Dalam komponen, tindakan dikirimkan seperti biasa:
AddTodo.js import { connect } from 'react-redux'; import { addTodo } from '../actions'; import NewTodo from '../components/NewTodo'; const mapDispatchToProps = dispatch => { return { onAddTodo: todo => { dispatch(addTodo(toto)); } }; }; export default connect( null, mapDispatchToProps )(NewTodo);
Dalam aksinya sendiri, situasinya jauh lebih menarik. Di sini kita akan menggunakan perpustakaan
Axios untuk permintaan ajax. Jika Anda belum menginstalnya, maka tambahkan seperti ini:
Kami akan membuat permintaan POST ke alamat -
jsonplaceholder.typicode.com/todos :
tindakan / 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 bagaimana pembuat tindakan
addTodo kami mengembalikan fungsi, bukan tindakan biasa dari objek. Fungsi ini mengambil argumen pengiriman dari toko.
Di dalam tubuh fungsi, pertama-tama kami mengirim tindakan sinkron biasa, yang melaporkan bahwa kami mulai menambahkan todo baru menggunakan API eksternal. Dengan kata sederhana - permintaan dikirim ke server. Kemudian, kami benar-benar membuat permintaan POST ke server menggunakan Axios. Dalam hal jawaban afirmatif dari server, kami mengirimkan tindakan tersinkronisasi menggunakan data yang diterima dari server. Tetapi jika ada kesalahan dari server, kami mengirimkan tindakan sinkron lain dengan pesan kesalahan.
Ketika kami menggunakan API yang benar-benar eksternal (jarak jauh), seperti
JSONPlaceholder dalam kasus kami, mudah untuk melihat bahwa ada penundaan hingga respons dari server tiba. Tetapi jika Anda bekerja dengan server lokal, jawabannya mungkin datang terlalu cepat, sehingga Anda tidak akan melihat penundaan. Jadi untuk kenyamanan Anda, Anda dapat menambahkan penundaan buatan saat mengembangkan:
action / index.js (sepotong kode) 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)); }); }; };
Dan untuk menguji skrip dengan kesalahan, Anda dapat langsung melemparkan kesalahan:
action / index.js (sepotong kode) export const addTodo = ({ title, userId }) => { return dispatch => { dispatch(addTodoStarted()); axios .post(ENDPOINT, { title, userId, completed: false }) .then(res => { throw new Error('NOT!');
Demi kelengkapan, berikut adalah contoh bagaimana penurun todo kami mungkin terlihat untuk memproses "siklus hidup" lengkap dari permintaan:
reducers / todoReducer.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; } }
getState
Fungsi yang dikembalikan oleh pembuat tindakan asinkron menggunakan Redux-Thunk juga menerima metode
getState sebagai argumen kedua, yang memungkinkan Anda untuk mendapatkan negara langsung di dalam pembuat tindakan:
action / index.js (sepotong kode) export const addTodo = ({ title, userId }) => { return (dispatch, getState) => { dispatch(addTodoStarted()); console.log('current state:', getState());
Saat menjalankan kode ini, status saat ini hanya akan ditampilkan ke konsol. Sebagai contoh:
{loading: true, todos: Array(1), error: null}
Menggunakan getState bisa sangat berguna ketika Anda perlu bereaksi secara berbeda, tergantung pada kondisi saat ini. Misalnya, jika kami membatasi jumlah maksimum elemen todo hingga 4, kami dapat keluar dari fungsinya jika batas ini terlampaui:
action / index.js (sepotong kode) export const addTodo = ({ title, userId }) => { return (dispatch, getState) => { const { todos } = getState(); if (todos.length >= 4) return; dispatch(addTodoStarted());
Fakta menyenangkan - tahukah Anda bahwa kode Redux-Thunk hanya terdiri dari 14 baris? Anda dapat memeriksa sendiri bagaimana muxleware Redux-Thunk bekerja di bawah tenda
Tautan ke artikel asli -
Tindakan Reduks Asinkron Menggunakan Redux Thunk .