12/08/2018, 17:12

Reactjs Redux Observable

Để có thể quản lý state và props trong ứng dụng react js của bạn thì mô hình Redux cung cấp một giải pháp quản lý bao gồm action , reducer và store . Trong đó Redux- Observable là một tùy chọn trung gian cho phép bạn xử lý logic không đồng bộ . Khi sử dụng Redux- Observable trong ứng dụng ...

Để có thể quản lý state và props trong ứng dụng react js của bạn thì mô hình Redux cung cấp một giải pháp quản lý bao gồm action, reducerstore .
Trong đó Redux- Observable là một tùy chọn trung gian cho phép bạn xử lý logic không đồng bộ . Khi sử dụng Redux- Observable trong ứng dụng của bạn. Bạn cần phải cung cấp một function Observable input và Observable output . Chức năng này đươc gọi là Epic .

Epics

Để hiểu rõ hơn về redux- observable tôi sẽ trình bày một ví dụ

# epics/user_epic.js
import 'rxjs';
import {Observable} from 'rxjs';

const FETCH_USER = 'FETCH_USER';
const FETCH_USER_FULFILLED = 'FETCH_USER_FULFILLED';
const FETCH_USER_REJECTED = 'FETCH_USER_REJECTED';
const FETCH_USER_CANCELLED = 'FETCH_USER_CANCELLED';

const fetchUser = id => ({ type: FETCH_USER, payload: id });

const fetchUserFulfilled = item => ({ type: "ADD_ITEM", item });

const cancelFetchUser = () => ({ type: FETCH_USER_CANCELLED });

const fakeAjax = url =>
  Observable.of({
    item: url.substring(url.lastIndexOf('/') + 1)
  }).delay(1000);
  
const fetchUserEpic = action$ =>
  action$.ofType(FETCH_USER)
    .mergeMap(action =>
      fakeAjax(`/api/users/${action.payload}`)
        .map(response => fetchUserFulfilled(response.item))
        .takeUntil(action$.ofType(FETCH_USER_CANCELLED))
    );

export default fetchUserEpic

Ở đây chúng ta lắng nghe action có type là : "FETCH_USER" . Nếu có action này thì sẽ lấy dữ liệu user từ hàm fakeAjax và trả dữ liệu vào fetchUserFulfilled với type : "ADD_ITEM" .

Reducer

# reducer/user_reducer
....

var dataReducer = (state = { }, action) => {
  switch (action.type){
    case "ADD_ITEM":
      return [...state, action.item]
    case "REMOVE_ITEM":
      ....
    default:
      ....
  }
}

var reducer = combineReducers({ 
  user: dataReducer
})

export default reducer ;

Tạo reducer xử lý action có type: "ADD_ITEM" . Thêm giá trị của action.tiem vào state.

Store

import reducer from './reducer/user_reducer';
import {createEpicMiddleware} from 'redux-observable';
import rootEpic from './epics/user_epic';
import { createStore } from 'redux';
import {applyMiddleware} from 'redux';

var epicMiddleware = createEpicMiddleware(rootEpic);
var store = createStore(reducer, applyMiddleware(epicMiddleware));

export default store;

Component . bắt sự kiện onsubmit

import React, { Component } from 'react';
import {connect} from 'react-redux';

class Noteform extends React.Component {

  add_note(e){
    e.preventDefault();
    var {dispatch} = this.props;
    dispatch({type: "FETCH_USER", payload: this.refs.txt.value });
  }

  render(){
    return (
      <form onSubmit = {this.add_note.bind(this)} >
        <input type = "text" placeholder = "Add note" ref= "txt" />
        <br/>
        <button>Add</button>
      </form>
    )
  }

}

export default connect(function(state){
  return { data: state.data }
})(Noteform)

https://redux-observable.js.org/docs/recipes/Cancellation.html

https://jsbin.com/fivaca/8/edit?html,css,js,output

Thank you for reading !!

0