目录↑

redux学习笔记

By blockXun

原理

redux是对于flux的完美实现,redux和react搭配很完美,但是redux是独立的,并不是基于react使用的

Redux 的工作流程
redux

以下仅为个人理解,可能不准确(从store向下开始)

  • store 是个容器,用于储存数据(state),只能有一个store
  • state 数据,某个状态下的数据
  • react Component 组件,通过操作执行 action creators
  • action react Component中的操作,react Component中无法直接获取和修改state,要通过action修改(改变state的唯一方式是通过触发action来修改)
  • dispatch(action) view发出action的方法,他接受一个形参,形参的值为描述action的动作(只发出,不是接受)
  • previousState,action store接收到 action 后,调用 reducer 传入 previousState,action (老状态和action),执行reduces
  • reducers 通过store 接收 action ,然后根据 action 返回新的state
  • newState 返回的新的state, view 层通过 store.getState 获取新的 state

安装

npm install --save redux react-redux

创建基础store文件

引入redux中的createStore,通过他创建store文件

import { createStore } from "redux";

const store = createStore(reducer); // reducer在下边代码块中会演示创建
export default store;

然后创建reducer,reducer为store中要存储的数据(是一个function

function reducer(state = 0, action) {
    if (action.type !== "reducer") return state
    return action.payload ? action.payload : state
}

state 为存储的数据(上一次传入的值,如果是第一次获取state,默认为0)
action 为调用function 传入的参数

store.js文件整体代码

import { createStore } from "redux";

function reducer(state = 0, action) {
    if (action.type !== "reducer") return state
    return action.payload ? action.payload : state
}

const store = createStore(reducer); // reducer在下边代码块中会演示创建
export default store;

获取数据 (getState)

在使用时,需要在页面中先引入store文件,然后通过getState获取到store中的数据

import store from "../store/store.js"
...
function getStore () {
    console.log(store.getState())
}
...

Action触发 (dispatch)

通过dispatch触发Action来改变store中存储的值

import store from "../store/store.js"
...
function setStore () {
    store.dispatch({
        type: "reducer",
        payload: 10
    })
}
// store.getState() // 10

多任务方法 (combineReducers)

按照上边方法,redux只能存储一个值,如果想存储多个,需要 combineReducers 调用一下

import { createStore, combineReducers } from "redux"; // 需要引入 combineReducers

function reducer(state = 0, action) {
    if (action.type !== "reducer") return state
    return action.payload ? action.payload : state
}

function counter(state = 0, action) {
  if (action.type !== "counter") return state
  return action.payload ? state + action.payload : state
}

// const store = createStore(reducer); // 之前的写法

const store = combineReducers({
    reducer,
    counter
})

export default store;

redux中间件 (applyMiddleware)

applyMiddleware 是redux插件默认带的一种方法,为store添加中间件。

applyMiddleware将所有中间件组成一个数组,依次执行

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer);
    var dispatch = store.dispatch;
    var chain = [];

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);

    return {...store, dispatch}
  }
}

//执行顺序解析
//中间件数组传入{getState: store.getState,dispatch: (action) => dispatch(action)} => 
//compose合并新中间件数组 并传入dispatch=>
//执行完所有中间件函数后返回store和dispatch

applyMiddlewares 返回的是store 对象

部分摘录:CSDN博主qdmoment

异步处理 (redux-thunk)

通过react-thunk 可以进行异步处理

安装 npm i --save redux-thunk

import thunk from 'redux-thunk' // 引入
...
var store = createStore(rReducers, applyMiddleware(thunk)) // 注册
export default store

异步组件书写方法和同步组件类似,如果是异步,需要返回一个promise对象

function strCounter(state = 'aaa', action) {
    if (action.type !== "strCounter") return state
    if (action.payload) {
        var data = new Promise((resolve, reject) => {
        setTimeout(() => {
            return '2222'
        },10000)
        })
        return data
    } else {
        return state
    }
}

react-thunk 源码

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

源码来源:简书博主zhangwang