One place for hosting & domains

      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