首先安装redux-thunknpm install redux-thunk
其次在创建store的时候,使用thunk中间件,照着官方文档,一步一步去配置,通过enhancer 这样一个内容,把他传递给createStore的第二个参数,使得我们这样一个store仓库,既使用了thunk又使用了REDUX_DEVTOOLS开发者工具。
store文件夹下的index.js
import { createStore, applyMiddleware, compose } from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';
// compose需要引入
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk),
);
//创建store的时候,使用reducer构建初始数据,创建store的时候,store会使用一个中间件,也就是thunk的中间件
const store = createStore(
reducer,
enhancer
);
export default store;
配置好redux-thunk开发环境后,使得我们可以在action中使用异步的代码。
打开之前写得todolist之后,当组件挂载完成之后,以前创建一个action只能是一个js对象,现在当使用了redux-thunk之后,即使getTodoList返回的不是一个对象而是一个函数,也可以通过store.dispatch(action);发送给store了。
componentDidMount(){
// axios.get('/list.json').then((res)=>{
// const data = res.data;
// const action = initListAction(data);
// store.dispatch(action);
// })
const action = getTodoList();
store.dispatch(action);
// console.log(action);
}
实际上 store只能接受一个对象,store发现你这是一个函数,就会做帮你自动的执行action对应的这个函数,也就是在获取json数据的那个函数,你获取了数据之后,你就要改变store的数据,又要走redux的流程,先创建一个action
// 正常来说 return出去的是一个对象,但是使用redux之后,可以return出去一个函数,在这个函数里可以做异步的操作
// 当调用getTodoList生成内容函数的时候,这个函数能够接收store的dispatch
export const getTodoList = () => {
return (dispatch) => {
axios.get('/list.json').then((res)=>{
const data = res.data;
const action = initListAction(data);
dispatch(action);
// console.log(data);
// const action = initListAction(data);
// store.dispatch(action);
})
}
}
随着你代码量的提升,你对代码的理解,大家会逐步理解,把异步函数放在组件的生命周期函数里做,这个生命函数有可能会变得越来越复杂,越来越多,然后这个组件就会变得越来越大。
TodoList.js
import React,{Component} from 'react';
import 'antd/dist/antd.css';
import store from './store';
import { getInputChangeAction, getAddItemAction, getDeleteItemAction, getTodoList } from './store/actionCreators';
import TodoListUI from './TodoListUI';
class TodoList extends Component{
constructor(props){
super(props);
this.state=store.getState();
this.handleInputChange=this.handleInputChange.bind(this);
this.handleBtnClick=this.handleBtnClick.bind(this);
this.handleStoreChange=this.handleStoreChange.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
//store里面的数据只要发生改变,subscribe里面函数就会被自动的执=行
store.subscribe(this.handleStoreChange);
}
render(){
return (
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleBtnClick={this.handleBtnClick}
handleItemDelete= {this.handleItemDelete}
/>
)
}
componentDidMount(){
// axios.get('/list.json').then((res)=>{
// const data = res.data;
// const action = initListAction(data);
// store.dispatch(action);
// })
const action = getTodoList();
store.dispatch(action);
// console.log(action);
}
handleInputChange(e){
// 去改变store里面的内容,首先要创建一句话,告诉store
const action = getInputChangeAction(e.target.value);
// 将这句话传递给store
store.dispatch(action);
}
handleStoreChange(){
//当感知到store的数据变化的时候,调用store.getState()方法,
//从store里面重新取一次数据,然后调用setState替换当前组件里的数据
// 这样组件里的数据,就和store里的数据同步了
this.setState(store.getState());
}
handleBtnClick(){
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index){
const action = getDeleteItemAction(index);
store.dispatch(action);
// alert(index);
}
}
export default TodoList;
TodoListUI.js
import React from 'react';
import { Input, Button, List } from 'antd';
const TodoListUI = (props)=>{
return (
<div style={{marginTop:'10px',marginLeft:'10px'}}>
<div>
<Input
value={props.inputValue}
placeholder='todo info'
style={{width:'300px',marginRight:'10px'}}
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.handleItemDelete(index)}}>{item}</List.Item>)}
/>
</div>
)
}
export default TodoListUI;
ActionCreators.js
import axios from 'axios';
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes';
export const getInputChangeAction =(value)=>({
type: CHANGE_INPUT_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
});
// 正常来说 return出去的是一个对象,但是使用redux之后,可以return出去一个函数,在这个函数里可以做异步的操作
// 当调用getTodoList生成内容函数的时候,这个函数能够接收store的dispatch
export const getTodoList = () => {
return (dispatch) => {
axios.get('/list.json').then((res)=>{
const data = res.data;
const action = initListAction(data);
dispatch(action);
// console.log(data);
// const action = initListAction(data);
// store.dispatch(action);
})
}
}
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';