Redux

Redux介绍及核心API

是由: reducer + flux 两个辅助框架结合而成;

  • createStore : 创建一个store数据管理库;
  • store.dispatch : 通知store,根据指令,改变数据;
  • store.getState : 获取store中的数据;
  • store.subscribe : 函数订阅store中的数据,当数据发生改变时,触发函数执行,更新数据;

如何在React工程项目中使用Redux

  1. src目录下,创建一个新的目录store;
  2. ,在store下创建index.js文件,执行以下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import {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
33
import {
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
}

  1. store文件目录下,新建actionCreator.js文件,写入代码:
    为方便代码测试,以及代码的可读性和维护性
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import {
    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需注意的问题点

  1. store只有唯一一个;
  2. 只有store才能改变自己的数据,reducer只是定义常量接收,待数据改变后,返回store一个新数据;
  3. reducer模块返回一个纯函数;
  4. 纯函数:给定固定的输入,就一定会有固定的输出,且没有其他副作用;

中间件redux-thunk 及设置redux本地数据调试工具

定义:中间件可以理解为对store中的dispatch方法重新封装升级,
没引用中间件,dispacth只能将action对象传递给store
引用中间件后,action可以定义为函数,dispatch会将action的函数执行,并将自己作为实参传入;

  1. 安装: npm install redux-thunk --save
  2. 在store目录下配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import {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
    24
    function* 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;
-------------本文结束感谢您的阅读-------------