Tutorial

Memahami Aksi Redux Asinkron dengan Redux Thunk

Published on January 6, 2021
    authorauthor

    Alligator.io and Bradley Kouchi

    Bahasa Indonesia
    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:

    1. 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.

    Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

    Learn more about our products

    About the authors
    Default avatar
    Alligator.io

    author



    Still looking for an answer?

    Ask a questionSearch for more help

    Was this helpful?
     
    Leave a comment
    

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Become a contributor for community

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    DigitalOcean Documentation

    Full documentation for every DigitalOcean product.

    Resources for startups and SMBs

    The Wave has everything you need to know about building a business, from raising funding to marketing your product.

    Get our newsletter

    Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

    New accounts only. By submitting your email you agree to our Privacy Policy

    The developer cloud

    Scale up as you grow — whether you're running one virtual machine or ten thousand.

    Get started for free

    Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

    *This promotional offer applies to new accounts only.