天天看點

redux-saga中間件的使用

公衆号:CS阿吉

todulist.js
//這個算是redux進階的Demo
import React, { Component } from "react";
import store from "../../store";
import {
  getInputChangeValue,
  getAddItemAction,
  getDeleteItemAction,
  initListAction,
  getTodoList
} from "../../store/actionCreaters";
import ToDoListUI from './ToDoListUI';

class ToDoListUp extends Component {
  constructor(props) {
    super(props);
    this.state = store.getState();
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleStoreChange = this.handleStoreChange.bind(this);
    this.handleButtonClick = this.handleButtonClick.bind(this);
    /**
     * 頁面上的内容并沒有随着store的更新而更新,是以如下操作:
     * store發生改變,則subscribe()綁定的函數會自動執行
     */
    store.subscribe(this.handleStoreChange);
  }

  componentDidMount() {
      const action = getTodoList();
    //   當調用store.dispatch把action發給store的時候,action會自動執行。
      store.dispatch(action);
  }

  // input值改變觸發action
  handleInputChange(e) {
    //定義action兩種方式,下面是最原始的一種:(1)
    // const action = {
    //   type: CHANGE_INPUT_VALUE,
    //   value: e.target.value
    // };
    //下面是改進的方式:(2)
    const action = getInputChangeValue(e.target.value);
    store.dispatch(action);

    console.log(e.target.value);
  }
  // 重新渲染頁面資料
  handleStoreChange() {
    this.setState(store.getState());
  }
  // 送出輸入内容
  handleButtonClick() {
    const action = getAddItemAction();

    store.dispatch(action);
  }
  // 點選清單電影名字,會删除電影
  handleItemDelete(index) {
    const action = getDeleteItemAction(index);
    store.dispatch(action);
  }

  render() {
    return (
      <ToDoListUI
        list={this.state.list}
        inputValue={this.state.inputValue}
        handleInputChange={this.handleInputChange}
        handleButtonClick={this.handleButtonClick}
        handleItemDelete={this.handleItemDelete}
      />
    );
  }
}

export default ToDoListUp;      
store.js
import { createStore, applyMiddleware, compose } from "redux";
import reducer from './reducer';
import thunk from "redux-thunk";

/**
 * 在建立store的時候使用reducer建構初始資料
 * 在建立的時候會使用thunk和__REDUX_DEVTOOLS_EXTENSION__ 中間件
 * 這裡的中間件指的是redux的中間件,而不是react
 * 
 */
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
    : compose;

const enhancer = composeEnhancers(
  applyMiddleware(thunk)
  // other store enhancers if any
);

const store = createStore(reducer, enhancer);

export default store;      
actionType.js
import {
  CHANGE_INPUT_VALUE,
  ADD_TODO_ITEM,
  DELETE_TODO_ITEM,
  INIT_LIST_ACTION
} from "./actionTypes";
import axios from 'axios';

export const getInputChangeValue = (value) => ({
        type: CHANGE_INPUT_VALUE,
        value:value
});

export const getAddItemAction = () => ({
         type: ADD_TODO_ITEM,
});

export const getDeleteItemAction = (index) => ({
         type: DELETE_TODO_ITEM,
         index
});

export const initListAction = (data) => ({
         type: INIT_LIST_ACTION,
         data
});

export const getTodoList = () => {
  return (dispatch) => {
    axios("http://localhost:3000/mock/list.json")
      .then(res => {
        const data = res.data;
        // 改變store中的資料
        const action = initListAction(data);
        dispatch(action);
      })
      .catch(err => {
        console.log(err);
      });
  }
};      
store.js
import { createStore, applyMiddleware, compose } from "redux";
import reducer from './reducer';
import thunk from "redux-thunk";
import createSagaMiddleware from "redux-saga";


/**
 * 在建立store的時候使用reducer建構初始資料
 * 在建立的時候會使用thunk和__REDUX_DEVTOOLS_EXTENSION__ 中間件
 * 這裡的中間件指的是redux的中間件,而不是react
 * 
 */
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
    : compose;

// create the saga middleware
const sagaMiddleware = createSagaMiddleware()

const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));


const store = createStore(reducer, enhancer);

export default store;
      
//建立一個saga.js檔案
import { takeEvery,put } from "redux-saga/effects";
import {GET_INIT_LIST} from './actionTypes';
import {initListAction} from './actionCreaters';
import axios from 'axios';

function* getInitList(){
    try{
        const res = yield axios.get("http://localhost:3000/mock/list.json");
        const action = initListAction(res.data);
        yield put(action);
    }catch(e){
        console.log("網絡請求失敗");
    }
}

//generator函數
function* todoSagas(){
    yield takeEvery(GET_INIT_LIST, getInitList);
}

export default todoSagas;      
store.js
import { createStore, applyMiddleware, compose } from "redux";
import reducer from './reducer';
import thunk from "redux-thunk";
import createSagaMiddleware from "redux-saga";
import todoSagas from './saga';


/**
 * 在建立store的時候使用reducer建構初始資料
 * 在建立的時候會使用thunk和__REDUX_DEVTOOLS_EXTENSION__ 中間件
 * 這裡的中間件指的是redux的中間件,而不是react
 * 
 */
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
    : compose;

// create the saga middleware
const sagaMiddleware = createSagaMiddleware()

const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));

const store = createStore(reducer, enhancer);

// then run the saga
sagaMiddleware.run(todoSagas);

// render the application

export default store;
      
todolist.js
//這個算是redux進階的Demo
import React, { Component } from "react";
import store from "../../store";
import {
  getInputChangeValue,
  getAddItemAction,
  getDeleteItemAction,
  initListAction,
  getInitList
  
} from "../../store/actionCreaters";
import ToDoListUI from './ToDoListUI';
import axios from 'axios';

class ToDoListUp extends Component {
  constructor(props) {
    super(props);
    this.state = store.getState();
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleStoreChange = this.handleStoreChange.bind(this);
    this.handleButtonClick = this.handleButtonClick.bind(this);
    /**
     * 頁面上的内容并沒有随着store的更新而更新,是以如下操作:
     * store發生改變,則subscribe()綁定的函數會自動執行
     */
    store.subscribe(this.handleStoreChange);
  }

  componentDidMount() {
    const action = getInitList();
    store.dispatch(action);
    console.log(action);
  }

  // input值改變觸發action
  handleInputChange(e) {
    //定義action兩種方式,下面是最原始的一種:(1)
    // const action = {
    //   type: CHANGE_INPUT_VALUE,
    //   value: e.target.value
    // };
    //下面是改進的方式:(2)
    const action = getInputChangeValue(e.target.value);
    store.dispatch(action);

    console.log(e.target.value);
  }
  // 重新渲染頁面資料
  handleStoreChange() {
    this.setState(store.getState());
  }
  // 送出輸入内容
  handleButtonClick() {
    const action = getAddItemAction();

    store.dispatch(action);
  }
  // 點選清單電影名字,會删除電影
  handleItemDelete(index) {
    const action = getDeleteItemAction(index);
    store.dispatch(action);
  }

  render() {
    return (
      <ToDoListUI
        list={this.state.list}
        inputValue={this.state.inputValue}
        handleInputChange={this.handleInputChange}
        handleButtonClick={this.handleButtonClick}
        handleItemDelete={this.handleItemDelete}
      />
    );
  }
}

export default ToDoListUp;      
actionType.js'
export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
export const INIT_LIST_ACTION = "init_list_action";
export const GET_INIT_LIST = "get_init_list";      
actionCreator.js
import {
  CHANGE_INPUT_VALUE,
  ADD_TODO_ITEM,
  DELETE_TODO_ITEM,
  INIT_LIST_ACTION,
  GET_INIT_LIST
} from "./actionTypes";
import axios from 'axios';

export const getInputChangeValue = (value) => ({
        type: CHANGE_INPUT_VALUE,
        value:value
});

export const getAddItemAction = () => ({
         type: ADD_TODO_ITEM,
});

export const getDeleteItemAction = (index) => ({
         type: DELETE_TODO_ITEM,
         index
});

export const initListAction = (data) => ({
         type: INIT_LIST_ACTION,
         data
});

export const getInitList = () => ({
  type:GET_INIT_LIST
})