React状态管理之redux-thunk

1,573 阅读3分钟

redux-thunk

为什么

异步action的使用场景:
当组件挂载完毕的时候,需要拿到接口返回的数据,但是接口数据并不能马上返回,是需要时间的,因此我们需要拿到数据之后,派发action,去修改store中的数据,更新组件。
流程:
派发action GET_LIST_ITEM => 发送请求,拿到数据之后,派发action  INIT_LIST_ITEM,更新store 
根据这个流程,一般情况下,Action Creator只能返回一个对象,所以我们使用redux-thunk之后,Action Creator可以返回一个函数,将请求接口和派发action封装为一个函数。
当dispatch的参数为一个函数时,会先执行这个函数。
这个函数接收两个参数,第一个参数是 dispatch方法,第二个参数是getState()方法。

const fetchPosts = ( postTitle) =>{
	return (dispatch,getState)=>{
  	axios.get('https://api.github.com/users/forsakensoul35/repos')
    .then( res => {
    	console.log(res.data)
      const action = {
      	type:INIT_LIST_ACTION,
        data:res.data
      }
      dispatch(action)
    })
  }
} 

做什么

redux-thunk是用来解决异步action的,比如请求远程接口数据,获取浏览器缓存等操作。

使用

// store/ index.js
import { createStore,applyMiddleware } from 'redux'
//导入thunk
import thunk from 'redux-thunk'
import reducer from './reducer'
// 创建store
const store = createStore(
	reducer,
  applyMiddleware(thunk)
)
export default store

案例:TodoList

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList'

ReactDOM.render(<TodoList />, document.getElementById('root'));

TodoList.js

import React,{ Component }  from 'react'
import 'antd/dist/antd.css'
import store from './store'
import { Input,Button,List } from 'antd'
import {
    ChangeInputValueAction,
    AddListItemAction,
    DeleteListItemAction,
    getListAction
} from './store/actionCreator'
export default class TodoList extends Component {
    constructor(props){
        super(props)
        this.state = store.getState()
        console.log(this.state)
        store.subscribe(()=>{
            this.setState(store.getState())
        })
    }
    componentDidMount =() =>{
        //当组件加载完毕的时候 去请求接口  返回初始化的list
        const action = getListAction()
        store.dispatch(action)
    }
    handleInputChange = (e) =>{
        // 需求: 当input改变时,修改state 
        // 修改state只能通过 dispatch action
        const action =ChangeInputValueAction(e.target.value)
        store.dispatch(action)
    }
    handleItemDelete = (index) => {
        // 点击item删除
        console.log(index)
        const action = DeleteListItemAction(index)
        store.dispatch(action)
    }
    handleBtnClick = () =>{
        const action = AddListItemAction()
        store.dispatch(action)
    }
    render(){
        return(
            /**
             * redux
             * 组成部分:
             * 1. store  
             * 2. reducer
             * 3. actionTypes
             * 4. actionCreator
             * 三大原则:
             * 1. store是唯一的
             * 2. store中的数据是只读的
             * 3. 修改数据 只能通过dispach方法
             * 数据流程
             * aactionCreatore => 创建action
             * 通过dispach派发acion store.dispatch
             * store接受到action之后,会自动转发给reducer
             * reducer是一个纯函数,接收action,以及preState,返回一个新的state给store
             * store接收新的state 更新 数据
             * 组件订阅store,当store中的数据更新时,执行对应的回调方法,获取getState()
             * 
             * 
             */
            /**
             * 需求描述
             * 一个input 一个 button 一个list
             */
            <div>
                <Input 
                    style= {{ width:'300px',marginLeft:'50px',marginTop:'50px'}} 
                    value={ this.state.inputValue}
                    onChange ={ this.handleInputChange}
                />
                <Button 
                    style= {{ marginLeft:'15px'}}
                    onClick = { this.handleBtnClick }
                >提交</Button>
                <List 
                    style= {{ 
                        width:'300px',
                        marginLeft:'50px',
                        marginTop:'20px',
                        backgroundColor:'#ccc'
                        }}
                        bordered
                        dataSource ={ this.state.list }
                        renderItem ={ (item,index) => (<List.Item onClick ={ ()=>this.handleItemDelete(index)}>{item}</List.Item>)}
                />
            </div>
        )
    }

}

store/index.js

import { createStore,applyMiddleware } from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'
// 使用redux-thunk
/**
 * 1. 引入 redux-thunk  
 * 2. 创建store的时候,将thunk作为第二个参数传入
 * 3. applyMiddleware
 */
const store = createStore(
    reducer,
    applyMiddleware(thunk)
)
export default store

store/reducer.js

const defaultState ={
    inputValue:'',
    list:[]
}
export default (state=defaultState,action)=>{
    if( action.type === 'change_input_value') {
        const newState = JSON.parse(JSON.stringify(state))
        console.log(action.value)
        newState.inputValue = action.value
        console.log(newState.inputValue)
        return newState
    }
    if( action.type === 'add_list_item') {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputValue)
        newState.inputValue = ''
        return newState
    }
    if(action.type ==="delete_list_item") {
        console.log(action.type)
        console.log(action.index)
        // console.log(value)
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.splice(action.index,1)
        return newState
    }
    if( action.type === 'init_list_item' ) {
        console.log(action.type)
        console.log(action.data)
        // console.log(value)
        const newState = JSON.parse(JSON.stringify(state))
        newState.list = newState.list+ action.data
        console.log(newState.list)
    }
    console.log(1)
    return state
}

store/actionTypes

export const CHANGE_INPUT_VALUE ='change_input_value'
export const DELETE_LIST_ITEM ='delete_list_item'
export const ADD_LIST_ITEM ='add_list_item'
export const INIT_LIST_ACTION ='init_list_item'
export const GET_LIST_ACTION ='get_list_action'

store/actionCreators

import {
    CHANGE_INPUT_VALUE,
    DELETE_LIST_ITEM,
    ADD_LIST_ITEM,
    GET_LIST_ACTION,
    INIT_LIST_ACTION
} from './actionTypes'
import axios from 'axios'
export const ChangeInputValueAction = (value) =>(
    {
        type:CHANGE_INPUT_VALUE,
        value
    }
)

export const AddListItemAction = () =>(
    {
        type:ADD_LIST_ITEM,
        
    }
)
export const DeleteListItemAction = (index) =>(
    {
        type:DELETE_LIST_ITEM,
        index
    }
)
export const InitListAction = (data) =>(
    {
        type:INIT_LIST_ACTION,
        data
    }
)


export const getListAction = () =>{
    // 使用了redux-thunk之后,可以返回一个函数  
    // 
    return (dispatch) =>{
        axios.get('https://api.github.com/users/forsakensoul35/repos')
        .then( res =>{
            console.log(res.data)
            // 拿到接口返回的数据之后
            // 更新state
            const action = InitListAction(res.data)
            dispatch(action)
        })
    }
}