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)
})
}
}