使用redux-thunk中间件实现ajax数据请求

上片文章,如果把一些复杂逻辑或者异步请求,放在同一个组件中,会显得冗长和难以管理。

我们可以使用react-thunk这个中间件进行管理。

 

可以把逻辑放在action中

 

优势:自动化测试特别方便

 

首先,学会使用:

redux-thunk

 

Installation
npm install redux-thunk
Then, to enable Redux Thunk, use applyMiddleware():

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

// Note: this API requires redux@>=3.1.0
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()

这个是redux devtools的 插件的使用的代码,要带上

 

 

如果只是使用thunk插件,那就:

import {createStore,applyMiddleware} from 'redux';
import reducer from './reducer';
import thunk from "redux-thunk";

/**
 * 在创建store的时候使用reducer构建初始数据
 * 在创建的时候会使用thunk和__REDUX_DEVTOOLS_EXTENSION__ 中间件
 * 这里的中间件指的是redux的中间件,而不是react
 * 
 */
const store = createStore(reducer, applyMiddleware(thunk));

export default store;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

 

如果使用thunk和redux devtools插件,那就

redux-devtools-extension

1.2 Advanced store setup
If you setup your store with middleware and enhancers, change:

  import { createStore, applyMiddleware, compose } from 'redux';

+ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+ const store = createStore(reducer, /* preloadedState, */ composeEnhancers(
- const store = createStore(reducer, /* preloadedState, */ compose(
    applyMiddleware(...middleware)
  ));

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
      // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
    }) : compose;

const enhancer = composeEnhancers(
  applyMiddleware(...middleware),
  // other store enhancers if any
);
const store = createStore(reducer, enhancer);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

实际上配置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;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

 

 

然后我们修改todolist组件中的代码,我们可以把componentDidMount中的代码移除,移动到action中去。

*当时候redux-thunk之后,我们当action可以是一个函数了。

修改如下:

actionCreaters.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);
      });
  }
};

因为在配置文件中我已经配置了axios的原型链,正常的话使用是this.axios就可以使用了。但是在这里不知道为啥子不好用,就采用常规办法吧。

 

 

修改todolist.js

核心代码:

componentDidMount() {
      const action = getTodoList();
    //   当调用store.dispatch把action发给store的时候,action会自动执行。
      store.dispatch(action);
      console.log(action);
  }

 

 

//这个算是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);
      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 (
      
    );
  }
}

export default ToDoListUp;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(react)