三个要注意的点:
1.store必须是唯一的,多个store是坚决不允许,只能有一个store空间
2.只有store能改变自己的内容,Reducer不能改变
3.Reducer必须是纯函数
其实最关键的还是基础的那个图,组件中更新state,要先dispatch(action),然后去store中找,store中没有,然后去reducer中找,reducer进行处理返回新的state。
actionCreators.js
import { CHANGE_INPUT,ADD_ITEM,DELETE_ITEM ,GET_LIST,GET_MY_LIST} from './actionTypes'
import axios from 'axios'
export const changeInputAction=(value)=>({
type:CHANGE_INPUT,
value
})
export const addItemAction=()=>({
type:ADD_ITEM
})
export const deleteItemAction=(index)=>({
type:DELETE_ITEM,
index
})
export const getListAction =(data)=>({
type:GET_LIST,
data
})
export const getMyListAction=()=>({
type:GET_MY_LIST
})
// export const getTodoList = () =>{
// return (dispatch)=>{
// axios.get('http://rap2api.taobao.org/app/mock/280858/example/1617624035824').then((res)=>{
// const data = res.data
// const action = getListAction(data)
// dispatch(action)
// })
// }
// }
actionTypes.js
export const CHANGE_INPUT='changeInput'
export const ADD_ITEM='addItem'
export const DELETE_ITEM='deleteItem'
export const GET_LIST='getList'
export const GET_MY_LIST='getMyList'
index.js
import {createStore,applyMiddleware,compose} from 'redux'//引入createState方法
import reducer from './reducer'
import createSagaMiddleware from 'redux-saga'
import mySagas from './sagas'
const sagaMiddleware =createSagaMiddleware();
const composeEnhancers=window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware))
const store=createStore(reducer,enhancer)//创建数据存储仓库
sagaMiddleware.run(mySagas)
export default store//暴露出去
reducer.js
import { CHANGE_INPUT,ADD_ITEM,DELETE_ITEM,GET_LIST} from './actionTypes'
//reducer 管理数据
const defaultState={
inputValue:'Writing something',
list:[
'早8点开晨会,分配今天的开发工作',
'早9点和项目经理作开发需求讨论会',
'晚5:30对今日代码进行review'
]
}//默认数据
export default (state=defaultState,action)=>{//是一个方法函数,state是需要管理的数据信息
if(action.type===CHANGE_INPUT){
let newState = JSON.parse(JSON.stringify(state))//深度拷贝state,深度拷贝,原和现互不影响.这里的state是由TodoList传过来的state
newState.inputValue = action.value//要记住这里是action.value action中的值和store里的值是不一样的
return newState
}
if(action.type===ADD_ITEM){
let newState = JSON.parse(JSON.stringify(state))//深度拷贝state,深度拷贝,原和现互不影响
newState.list.push(newState.inputValue) //这样也可以 [...newState.list,newState.inputValue]
newState.inputValue = ''
return newState
}
if(action.type===DELETE_ITEM){
let newState = JSON.parse(JSON.stringify(state))//深度拷贝state,深度拷贝,原和现互不影响
newState.list.splice(action.index,1) //这样也可以 [...newState.list,newState.inputValue]
return newState
}
if(action.type===GET_LIST){
let newState=JSON.parse(JSON.stringify(state))
newState.list=action.data.items
return newState
}
if(action.type===GET_LIST){
let newState=JSON.parse(JSON.stringify(state))
newState.list=action.data.items
return newState
}
return state
}
sagas.js
import {put, takeEvery} from 'redux-saga/effects'
import {GET_MY_LIST} from './actionTypes'
import {getListAction} from './actionCreators'
import axios from 'axios'
function* mySaga(){
yield takeEvery(GET_MY_LIST,getList)
}
function* getList(){
const res=yield axios.get('http://rap2api.taobao.org/app/mock/280858/example/1617624035824')
const action =getListAction(res.data)
yield put(action)
}
export default mySaga;
index.js
import React, { Component } 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 { Input,Button,List } from 'antd'
import store from './store'
import { CHANGE_INPUT,ADD_ITEM,DELETE_ITEM } from './store/actionTypes'
import { changeInputAction,addItemAction,deleteItemAction,getListAction,getTodoList,getMyListAction} from './store/actionCreators'
import TodoListUI from './TodoListUI'
import axios from 'axios'
class TodoList extends Component {
constructor(props) {
super(props);
this.state=store.getState()
this.changeInputValue=this.changeInputValue.bind(this)
this.storeChange=this.storeChange.bind(this)
this.clickBtn=this.clickBtn.bind(this)
store.subscribe(this.storeChange)
}
componentDidMount(){
const action =getMyListAction()
store.dispatch(action)
}
render() {
return (
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
changeInputValue={this.changeInputValue}
clickBtn={this.clickBtn}
deleteItem={this.deleteItem}
/>
);
}
changeInputValue(e){
const action=changeInputAction(e.target.value)
store.dispatch(action)//通过dispatch方法将action传给store
}
storeChange(){
this.setState(store.getState())
}
clickBtn(){
const action=addItemAction()
store.dispatch(action)
}
deleteItem(index){
const action=deleteItemAction(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'}}>
<div>
<Input
value={props.inputValue}
style={{width:'200px',marginRight:'10px'}}
onChange={props.changeInputValue}
/>
<Button
type='primary'
onClick={props.clickBtn}
>增加</Button>
</div>
<div style={{margin:'10px',width:'300px'}}>
<List
bordered
dataSource={props.list}
renderItem={(item,index)=>(
<List.Item
onClick={()=>{props.deleteItem(index)}}
>{item}</List.Item>)}
/>
</div>
</div>
);
}
export default TOdoListUI;