redux 及 react-redux基本用法及源码解析

本文介绍了redux和react-redux的基本用法,强调redux作为一个数据管理器,不仅限于与react搭配,核心在于store。文中详细讲解了store的四个关键函数,并提供了创建store、action和reducer的简单示例。对于异步操作,提到了thunk中间件的作用。最后预告源码解析将在下篇博客中展开。
摘要由CSDN通过智能技术生成

 某年某月某日,某师兄说:学一个东西,不能只停留在表面,只知道怎么用是完全不够的,

要清楚的明白,为什么这么做,为什么不那样做,还得从源码开始,虽然起步可能会比较坎坷,毕竟知识储备有限尴尬

点到为止了,所以我也就尝试去看了 redux 以及 react-redux 源码,确实坎坷惊恐

在此对看过的一些资料做一个总结。


先讲讲其基本用法,最后附上源码解析大笑

其实简单的应用,甚至只是一个单页应用,那完全是用不到 redux 的,只会让代码量提升了却没什么好处,出力不讨好。

redux 不仅仅只限于和 react 搭配使用,它可说是一个数据(state)管理器,也可在其他场景中使用。

当然 react-redux 就顾名思义不是适用于任何场景了。

如果用过 FLUX 的同学,应该会对 redux 的主要思想比较容易理解:

单项数据流,但存在与 FLUX比较大的差别是redux 整个应用只有一个数据源,也就是只有一个 store,在复杂的应用中也统一管理所有的数据。

我觉得 store 是整个 redux 的核心,最为核心的就是 store 的四个 function:

微笑dispatch:分发 Action 到对应的 Reducer后,根据 Reducer 逻辑更改store 中的 state,之后触发 subscribe的 listener,

微笑getState:获取当前store 中的 state 数据,

微笑subscribe: 注册 listener,在 state 变化时触发,

微笑replaceReducer:替换 Reducer,修改 state 变化逻辑,不是很常用。

我们需要做的是创建 store,Action,Reducer,最基本,最简单的写法:


//actionType
export const ACTION_TYPE = 'ACTION_TYPE';
//actionCreator
let actionCreator = (config) => {
    return {
        type: ACTION_TYPE, // 必须定义 type
        config // 可定义任何属性,都会传递到 reducer,用于修改 state
    }
}

action 其实就是一个普通对象,当然你也可以直接写这个对象,但存在诸多劣势。

import { ACTION_A, ACTION_B } from '../actions';
let initialState = { ... }
function example(state = initialState, action) {
    switch(action.type) {
        case ACTION_A:
          return Object.assign({}, state, action.config)
        case ACTION_B:
          return Object.assign({}, state, action.config)
	default:
	  return state
    }
}

reducer 里只做修改state,纯函数

import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux'
import thunk from 'redux-thunk';
import reducers from './reducers';
let store = createStore(reducers);
ReactDOM.render((
  <Provider store={store}>
   // ...
  </Provider>
), document.querySelector('#app'));

创建一个 store,也是整个应用唯一的 store。

Provider 是 react-redux 中提供的。可以通过Provider将 store 传递到包含在它之内的所有子组件里,但需配合 connect 使用。

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { actionA } from 'actions';
class ComponentA extends Component {
    constructor(props) {
        super(props);
    }
    componentDidMount() {
        let { dispatch } = this.props;
        dispatch(actionA())
    }
    render() {
//由于所用到的 state 都绑定到了 props 中,component 中用到的时候可在 props 中获取
	<div>{this.props.propA}</div>
    }
}let mapStateToProps = (state) => { 
// attention,会把最新的 state 数据绑定到组件 props 中。 
//只需绑定和本组件相关的 state 即可(state 是包含了整个应用的所有数据的。
let { reducerA, reducerB } = state; 
    return { 
        propA: reducerA.propA, 
        propB: reducerB.propB 
    }
};
export default connect(mapStateToProps)(ComponentA);
connect 也是 react-redux 中提供的,这里简单的介绍下,最基础的用法就是只传mapStateToProps 方法,

返回的是一个包含了调用 getState,subscribe 的原组件(这里即 ComponentA)。

这样就完成一整套简单的 redux 融合的 react 组件应用了。

但这样的数据交互都是同步的,无法支持 ajax 的异步请求。

如果想实现就需要加入 thunk中间件去完成,同时需改造 action,不仅仅是一个简单的普通 Object 即可完成的了。

微笑另一种方法即在 component 中创建store,在 component 内就能直接调用 store.dispatch,store.subscribe,store.getState 等方法,完成数据管理。

但这种写法有个坑,即比如在 componentDidMount中注册了 subscribe 的 listener 时会返回一个 unsubscribe 方法,

用于解绑的,必须在 componentWillUnmount 的时候执行该方法,不然会报警告,在组件卸载时仍在监听。

componentDidMount(){
    self.unsubscribe = subscribe(()=>{xxx});
}
componentWillUnmount(){
    self.unsubscribe();
}

需要异步请求时,需要对 store 和 action 进行改造加强:

export default function configureStore(initialState) {
  const store = createStore(rootReducer,initialState,applyMiddleware(
    thunkMiddleware,//支持异步操作
    createLogger()//输出 redux 的action 和 state相关 log
  ))
  return store;
}
action 需改成根据异步请求不同状态发出不同的 action,包装成一个方法来完成
export function  fetchAction() {
    return dispatch => {
        dispatch({
            type: 'REQUEST_POSTS'
        })
        return fetch(`xxxxx`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            }
        })
            .then(response => response.json())
            .then(function (json) {
                if (json.success) {
                    dispatch({
                        type: CATEGORIES_RECEIVE_POSTS,
                        data: json
                    })
                } else {
                    info('数据获取失败,请稍候再试!')
                }
            })
            .catch(e => {
                debugger;
            })
    }
}
直白的理解就是发起请求时发出一个 action(不真实改变 state,只改变请求状态),

请求返回成功一个action,失败一个 action 让 reducer 做出不同的对 state 的修改,即可完成异步请求。


源码解析接下一篇博客哟~




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值