Redux中发送异步请求及Redux中的React-thunk中间件使用(六)

ajax请求相关代码

TodoList.js

import React ,{
     Component}from 'react';
import store from './store/index';
import {
      getInputChangeAction,getddItemActiom,getDeleteItemAction, initListAction }from './store/actionCreator';
import TodoListUi from './TodoListUi';
import axios from 'axios';//进行ajax请求,需要引入axios模块
class TodoList extends  Component{
     
    constructor(props){
     
        super(props);
        this.state=store.getState();
        //监听store里面的变化,只要一变化
        //只要store里面的数据发生改变,则立即执行subscribe函数里的函数
        store.subscribe(this.handleStoreChange)
    }
    render(){
     
        return(
            <TodoListUi
                inputValue={
     this.state.inputValue}
                list={
     this.state.list}
                handleInputChange={
     this.handleInputChange}
                handleBtnClick={
     this.handleBtnClick}
                handleItemDelet={
     this.handleItemDelet}
            />
        )
    }
    //异步请求数据,放在生命周期函数componentDidMount中
    //视图渲染之后使用axios进行ajax请求,进行初始化
    componentDidMount(){
     
    	axios.get('/list.json').then((res) => {
     //请求成功执行的函数
		//请求成功就可以获取到res中的数据
		const data = res.data;
		//接下来修改store中的数据
		//创建action:action就是一个函数,接受一个data的变量,
		//返回一个对象,这个对象就是我们需要的action
		const action = initListAction(data)
		//有了action之后,要把action发送给store,通过store调用dispatch方法,
		//store拿着之前的数据和action一同自动传给reducer,
		//reducer拿到store中之前的数据以及action就可以进行操作了
		store.dispatch(action);
	})
    }
    
    handleInputChange=(e)=>{
     
        const action=getInputChangeAction(e.target.value);
        store.dispatch(action);
    };

    handleStoreChange=()=>{
     
        this.setState(store.getState())
    };

    handleBtnClick=()=>{
     
        const action=getAddItemActiom();
        store.dispatch(action);
    };

    handleItemDelet=(index)=>{
     
        const action=getDeleteItemAction(index);
        store.dispatch(action);
    }
}
export default TodoList ;

TodoListUi.js

import React ,{
     Component}from 'react';
import 'antd/dist/antd.css'
import {
     Input,Button,List} from 'antd'
const TodoListUi=(props)=>{
     
    return(
        <div style={
     {
     margin:'10px',marginLeft:'10px'}}>
            <div>
                <Input
                    value={
     props.inputValue}
                    placehoder="todo list "
                    style={
     {
     width:'300px'}}
                    onChange={
     props.handleInputChange}
                />
                <Button
                    type= "primary"
                    onClick={
     props.handleBtnClick}
                >提交</Button>
            </div>
            <List
                style={
     {
     marginTop:'10px',width:'300px'}}
                bordered
                dataSource={
     props.list}
                renderItem={
     (item,index) => (<List.Item onClick={
     ()=>{
     props.handleItemDelet(index)}} >{
     item}</List.Item>)}
                //调用父组件带参数的函数用箭头函数
            />
        </div>
    )
};
export default TodoListUi;

创建store:.store/index.js

import {
      createStore, applyMiddleware, compose  } from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
const store = createStore(
    reducer,//构建初始的数据
     window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
	window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
     
	}) 
export default store;

actionCreators.js

import {
      CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes'
export const getInputChangeAction = (value) => ({
     
    typt:CHANGE_INPUT_VALUE,
    value
});

export const getAddItemAction = () => ({
     
    typt:ADD_TODO_ITEM,
});
export const getDeleteItemAction = (index) => ({
     
    typt:DELETE_TODO_ITEM,
    index
});
export const initListAction = (data) => ({
     
    typt:INIT_LIST_ACTION,
    data
});

actionTypes.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';

reducer.js

const defaultState = {
     
    inputValue:'',
    list:[]
};
//reducer可以接受state,但是不能修改state
//纯函数指的是,给固定的输入,就一定会有固定的输出,而且不会有任何副作用
export default (state = defaultState, action) => {
     
    if(action.type === INIT_LIST_ACTION){
     
    	//将上一个state值深拷贝一份到newState,这样就可以修改newState的值了
        const newState = JSON.parse(JSON.stringify(state));
        newState.list = action.data;
        return newState;
    }
}

通过以上ajax请求功能,我们发现如果异步请求或者复杂的逻辑都放在一个组件中进行实行的时候,那么这个组件就会显得过于臃肿,当我们遇到这个异步请求或者非常复杂的逻辑的时候,我们可以把这些抽取到一个其他的地方进行统一管理。

那可以抽取到什么地方呢?这是redux中的redux-thunk这个中间件就可以帮助到我们,redux-thunk中间件可以是我们把这种异步请求或者非常复杂的逻辑放到action中取处理。

接下看这个redux-thunk这个中间件如何使用?

Redux-thunk作用:

简单说:当组件中有复杂的异步请求时,为了减少组件的复杂程度
把异步请求使用此中间件放在actionCreator.js中

查看redux-thunk的官网:https://github.com/reduxjs/redux-thunk
1、安装redux-thunk
npm install redux-thunk

2、安装好后如何使用呢:
首先在创建store的时候,要使用这个中间件,要从redux中引入applyMiddleware这个方法,import { createStore, applyMiddleware } from 'redux';引入这个方法的目的,是让我们可以使用中间件。
然后从redux-thunk这个库中引入thunk这个模块:import thunk from 'redux-thunk';

3、在创建store的时候,将applyMiddleware这个方法作为参数传入

import {
      createStore, applyMiddleware, compose  } from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
const store = createStore(
    reducer,//构建初始的数据 
    applyMiddleware(thunk)//在创建store的时候,这个方法表示:使用thunk这个中间件
export default store;

4、用于redux测试的window.__REDUX_DEVTOOLS_EXTENSION__ &&window.__REDUX_DEVTOOLS_EXTENSION__()这个东西也是redux中的一个中间件,使用该如何放?

使用store的高级设置:

import {
      createStore, applyMiddleware, compose  } from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
     }) : compose;
	//compose函数需要从redux中引出来

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

const store = createStore(
    reducer,//构建初始的数据
    enhancer
export default store;

5、设置好redux-thunk,接下来就可以围绕这个组件编写代码:
可以将组件中的异步操作的代码移动到action中了。之前对于未使用redux-thunk中间件的action,在actionCreatoes.js中每一个action都是一个函数,每一个函数都会返回一个对象,且只能返回对象。
Redux中发送异步请求及Redux中的React-thunk中间件使用(六)_第1张图片

当使用的redux-thunk之后,这个action就可以返回一个函数了,在这个函数里面我们就可以做异步的操作了。

//当调用getTodoList ,并生成一个action为函数的时候,
//这个函数会自动接受到store的dispatch方法
export const getTodoList = (data) => {
     
	return (dispatch) => {
     //可以接受到dispatch这个参数
		axios.get('/list.json').then((res) => {
     
		//请求成功就可以获取到res中的数据
		const data = res.data;
		//获取到数据以后,接下来修改store中的数据
		//store中的数据如何改变呢?
		//创建action
		const action = initListAction(data)
		dispatch(action);
	})
	}
};

6、在组件中componentDidMount生命周期函数中调用getTodoList 这个action就可以了。如何调用呢?

componentDidMount(){
     
	//现在这个action就不是一个对象了,而是一个函数了。
	const action = getTodoList ();
	//action是一个函数,应该怎么用呢?
	//在使用了redux-thunk之后,dispatch方法就可以接受一个函数了
	//直接将action传给store,当调用dispatch,把action传给store的时候,
	//这个action函数(ajax请求的函数)就会被执行,就会获取到数据data了
	store.dispatch(action)//在这里dispatch接受了一个函数,实际上store只能接受一个对象,
	//这是store会自动执行下这个action函数,这个函数就是`getTodoList `这个东西
}

你可能感兴趣的:(React,React异步请求)