+4

Tìm hiểu Redux sagas

1. Mở đầu

    Chào mọi người...😜😜😜😜 bây giờ mình lại nổi lên đây rồi. Lại chuỗi học reactjs nà. Bài trước mình có đi tìm hiểu về redux trong reactjs . Còn lần này mình lại cùng nhau đi tìm hiểu và học một kiến thức mới nhá..đó là kết hợp redux-sagas trong reactjs.

Nội dung

1. Khái niệm và tiện ích

2. Một chút ví dụ

1. Khái niệm và tiện ích

    Redux-Saga là một thư viện redux middleware, giúp quản lý những side effect trong ứng dụng redux trở nên đơn giản hơn. Bằng việc sử dụng tối đa tính năng Generators (function*) của ES6, nó cho phép ta viết async code nhìn giống như là synchronos.

Side effect là gì??

    Những xử lý ở REDUCER đều là xử lý đồng bộ. Nhưng trong ứng dụng thực tế thì ta cần nhiều hơn vậy. Ví dụ như ta dùng gọi API và lấy dữ liệu thì cần phải đợi lấy kết quả. Vậy những việc như thế trong lập trình hàm gọi nó là side effecrs.

Generator function là gì??

    Khác với function bình thường là thực thi và trả về kết quả, thì Generator function có thể thực thi, tạm dừng trả về kết quả. Từ khóa để làm được việc đấy là YIELD.

Redux-Saga hoạt động như thế nào??

    Đối với logic của saga, ta cung cấp một hàm cho saga, chính hàm này là hàm đứng ra xem xét các action trước khi vào store, nếu là action quan tâm thì nó sẽ thực thi hàm sẽ được thực thi, nếu bạn biết khái niệm hook thì hàm cung cấp cho saga chính là hàm hook.

    Điều đặc biệt của hàm hook này nó là một generator function, trong generator function này cóyield và mỗi khi yield ta sẽ trả về một plain object. Object trả về đó được gọi Effect object. effect object này đơn giản chỉ là một object bình thường nhưng chứa thông tin đặc biệt dùng để chỉ dẫn middleware của Redux thực thi các hoạt động khác ví dụ như gọi một hàm async khác hay put một action tới store. Để tạo ra effect object đề cập ở trên thì ta gọi hàm từ thư viện của saga là redux-saga/effects.

hoat động của redux

Sơ đồ hoạt động của sagas


Mình tìm hiểu thì dài vậy nhưng mình nghĩ nó là một thư viện giúp ứng dụng redux của bạn giao tiếp và không đồng bộ với bên ngoài, và chủ yếu là API.

2. Một chút ví dụ

tạo một project

npx create-react-app my-app

Thêm các thư viện cần thiết

yarn add redux

yarn add react-redux

yarn add redux-saga

Rồi chiến thôi các bạn, ở đây mình kết hợp cả kiến thức coi như đã biết của redux rồi nên chỉ giải thích phần liên quan tới sagas .. 😍😍😍😘😘😜😜😜

Đầu tiên mình sẽ tạo một số file

//types.js
export const REQUEST_FROM_JSON = 'REQUEST_FROM_JSON';
export const RECEVIE_DATA = 'RECEVIE_DATA';
export const ADD_USER = 'ADD_USER';

file này chưa các name case để tất cả các name case là đồng nhất

//actions.js
import * as types from './types';

export function getDataFromJson () {
    return {
        type: types.REQUEST_FROM_JSON
    }
}

export function getData (data) {
    return {
        type: types.RECEVIE_DATA,
        data
    }
}

Các hành động dùng để dispatch

//reducers.js
import * as types from './types';
const getDataFromJsonInitialState = {};
export function getDataFromJson (state = getDataFromJsonInitialState, action) {
    switch (action.type) {
        case types.RECEVIE_DATA:
            return {...getDataFromJsonInitialState, 'users': action.data};
        case types.REQUEST_FROM_JSON:
            return {...getDataFromJsonInitialState, 'success': true}
        default:
            return state;
    }
}

Nơi đây thực thi và lưu vào store...giờ đến file sagas.js xem chúng ta có gì nha.

//sagas.js
import { takeLatest, call, put } from "redux-saga/effects";
import * as actions from './actions';
import * as types from './types';
import callApi from './../callApi';

export function* watcherSaga () {
    yield takeLatest(types.REQUEST_FROM_JSON, workerSaga);
}

function fetchData () {
    return callApi('student/get-all');
}

function* workerSaga() {
    try {
        const users = yield call(fetchData);
        yield put(actions.getData(users.data));

    } catch (error) {
        console.log(error);
    }
    
}

Vâng đến đây mình giải thích những gì mình dùng trong này

đầu tiên là

takeLastest(): Có nghĩa là nếu chúng ta thực hiện một loạt các actions, nó sẽ chỉ thực thi và trả lại kết quả của của actions cuối cùng.

call(): gọi function. Nếu nó return về một promise, tạm dừng saga cho đến khi promise được giải quyết.

put(): dispatch một action

watcherSaga : một generator function sẽ gửi action được dispatched tới Store

workerSaga: dùng để gọi hàm call lên api và trả về kết quả.

trên là công dụng của chúng và cách dùng bên trên..giờ ta đên nơi sử dụng nhá

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from './../redux/actions';
import { withRouter } from 'react-router-dom'
import './../users.css';
class UserItem extends Component {
    constructor(props) {
        super(props);
        this.state = {
            users: []
        }
        
    }
    componentWillMount() {
        this.props.getUser();
    }

    delete = (id) => {
        console.log(id);
    }
    render() {
        return (
            <div>
                <table className="table">
                    <thead>
                        <tr>
                            <th>STT</th>
                            <th>Name</th>
                            <th>Mobile</th>
                            <th>Address</th>
                            <th></th>
                        </tr>
                    </thead>
                    <tbody>
                        {
                            this.props.users && this.props.users.map((value, key) => {
                                return (
                                    <tr key={key}>
                                        <td>{ key + 1 }</td>
                                        <td>{ value.name }</td>
                                        <td>{ value.mobile }</td>
                                        <td>{ value.address }</td>
                                        <td>
                                            <button className="btn btn-outline-danger" onClick={() => this.delete(value.id)}>Delete</button> 
                                            <button className="btn btn-outline-warning">Edit</button>
                                        </td>
                                    </tr>
                                    
                                )
                            })
                        }
                    </tbody>
                </table> 
            </div>
        );
    }
}
function mapStateToProps(state) {
    return {
        users: state.users
      }
}
const mapDispatchToProps = (dispatch) => {
    return {
        getUser: () => {
            dispatch(actions.getDataFromJson())
          }
    }
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(UserItem));

    Các ban thấy không mình gọi như bình thường mà không cần tao hay gọi đến bất kì function nào tác động đến api rồi mới truyền ngược vào store..ở đây mình có thể làm đc cả 2 trong một lần gọi function được truyền từ store.

Tổng kết

    Qua quá trình mình làm thì ngoài các khái niệm trên thì mình rút ra đó là, sagas giúp mình thực hiện các việc mà chúng ta không thao tác, giảm bớt giai đoạn cũng như xử lý..ví dụ trước kia không dùng sagas thì chúng phải tự dispatch một action để gọi api và lấy kết quả rồi sau đó mới dispatch đưa vào store. Bây giờ đã có sagas giúp ta làm những công đoạn như vậy.

    Qua bài trên mong rằng giúp được phần nào quá trình học tập của các bạn cũng như đây là bài note lại kiến thức cho mình.

    Mọi ý kiến đóng góp mọi người cmt ở dưới nhá!!!

Tài liệu tham khảo

Giới thiệu Redux-Saga

Redux-Saga tutorial for beginners and dog lovers


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.