Redux介绍及核心API
是由: reducer + flux 两个辅助框架结合而成;
- createStore : 创建一个store数据管理库;
- store.dispatch : 通知store,根据指令,改变数据;
- store.getState : 获取store中的数据;
- store.subscribe : 函数订阅store中的数据,当数据发生改变时,触发函数执行,更新数据;
如何在React工程项目中使用Redux
- 在src目录下,创建一个新的目录store;
- ,在store下创建index.js文件,执行以下代码:
1
2
3
4
5
6
7
8
9
10import {createStore} from 'redux';
import reducer from './reducer.js';
const store = createStore(
reducer,
// 设置本地redux调试工具
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store ;
3.在store目录下,新建一个文件reducer.js,执行以下代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import {
CHANGE_INPUT_VALUE,
ADD_TODO_ITEM,
DELETE_TODO_ITEM
} from './actionType.js';
const defaultState = {
inputValue:'123',
list:[1,2,3]
}
// 可以接受state,但是绝不能改变state数据
// 定义一个常量赋值state,然后对这个常量进行改变;
export default (state = defaultState,action) => {
// console.log(state,action)
if(action.type === CHANGE_INPUT_VALUE){
// 深层拷贝state
const newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if(action.type === ADD_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
if(action.type === DELETE_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index,1)
return newState
}
return state
}
- 在store文件目录下,新建actionCreator.js文件,写入代码:
为方便代码测试,以及代码的可读性和维护性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import {
CHANGE_INPUT_VALUE,
ADD_TODO_ITEM,
DELETE_TODO_ITEM
} from './actionType.js';
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
})
Redux需注意的问题点
- store只有唯一一个;
- 只有store才能改变自己的数据,reducer只是定义常量接收,待数据改变后,返回store一个新数据;
- reducer模块返回一个纯函数;
- 纯函数:给定固定的输入,就一定会有固定的输出,且没有其他副作用;
中间件redux-thunk 及设置redux本地数据调试工具
定义:中间件可以理解为对store中的dispatch方法重新封装升级,
没引用中间件,dispacth只能将action对象传递给store
引用中间件后,action可以定义为函数,dispatch会将action的函数执行,并将自己作为实参传入;
- 安装:
npm install redux-thunk --save
- 在store目录下配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import {createStore,applyMiddleware,compose} from 'redux';
import reducer from './reducer.js';
import thunk from 'redux-thunk';
// 设置本地redux调试工具
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
// other store enhancers if any
);
const store = createStore(
reducer,
enhancer
)
export default store ;
中间件 saga 的使用方法
在store数据库中使用saga中间件
1
2
3
4
5
6
7
8// 导入saga包
import createSagaMiddleware from 'redux-saga';
// 导入本地的saga函数模块,异步操作主要发生这个自定义的模块内
import todoSaga from './sagas.js';
// 定义一个使用saga中间件的函数
const sagaMiddleware = createSagaMiddleware();
// run API 导入这个自定义的函数(异步请求数据)
sagaMiddleware.run(todoSaga);demo : todoSaga.js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function* getInitList (){
try {
const res = yield axios.get('pathname')
const action = getListAction(res.data);
yield put(action)
}catch(e){
console.log('数据请求失败')
}
}
// async function getInitList(){
// try{
// const res = await axios.get('pathname')
// const action = getListAction(res.data)
// await put(action)
// }catch(e){
// console.log('数据请求失败')
// }
// }
generator函数 配合yield指令,执行
takeEvery会捕捉到dispatch派发的action,并执行后面对应的函数
function* todoSaga() {
yield takeEvery(GET_INIT_LIST, getInitList);
}
export default todoSaga;