redux 及 react-redux基本用法及源码解析
2017-01-12 15:52
621 查看
某年某月某日,某师兄说:学一个东西,不能只停留在表面,只知道怎么用是完全不够的,
要清楚的明白,为什么这么做,为什么不那样做,还得从源码开始,虽然起步可能会比较坎坷,毕竟知识储备有限
。
点到为止了,所以我也就尝试去看了 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,最基本,最简单的写法:
action 其实就是一个普通对象,当然你也可以直接写这个对象,但存在诸多劣势。
reducer 里只做修改state,纯函数。
创建一个 store,也是整个应用唯一的 store。
Provider 是 react-redux 中提供的。可以通过Provider将 store 传递到包含在它之内的所有子组件里,但需配合 connect 使用。
返回的是一个包含了调用 getState,subscribe 的原组件(这里即 ComponentA)。
这样就完成一整套简单的 redux 融合的 react 组件应用了。
但这样的数据交互都是同步的,无法支持 ajax 的异步请求。
如果想实现就需要加入 thunk中间件去完成,同时需改造 action,不仅仅是一个简单的普通 Object 即可完成的了。
另一种方法即在 component 中创建store,在 component 内就能直接调用 store.dispatch,store.subscribe,store.getState 等方法,完成数据管理。
但这种写法有个坑,即比如在 componentDidMount中注册了 subscribe 的 listener 时会返回一个 unsubscribe 方法,
用于解绑的,必须在 componentWillUnmount 的时候执行该方法,不然会报警告,在组件卸载时仍在监听。
需要异步请求时,需要对 store 和 action 进行改造加强:
请求返回成功一个action,失败一个 action 让 reducer 做出不同的对 state 的修改,即可完成异步请求。
源码解析接下一篇博客哟~
要清楚的明白,为什么这么做,为什么不那样做,还得从源码开始,虽然起步可能会比较坎坷,毕竟知识储备有限
。
点到为止了,所以我也就尝试去看了 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 的修改,即可完成异步请求。
源码解析接下一篇博客哟~
相关文章推荐
- 【安卓网络请求开源框架Volley源码解析系列】初识Volley及其基本用法
- React实战-深入源码了解Redux用法之Middleware
- 【安卓网络请求开源框架Volley源码解析系列】初识Volley及其基本用法
- React实战-深入源码了解Redux用法之Provider
- React-Redux的基本用法
- 【安卓网络请求开源框架Volley源码解析系列】初识Volley及其基本用法
- React实战-深入源码了解Redux用法之Reducers
- 关于react-redux中的connect用法介绍及原理解析
- 详解关于react-redux中的connect用法介绍及原理解析
- React实战-深入源码了解Redux用法之Connect
- Srping源码深度解析(二)容器的基本用法
- 【安卓网络请求开源框架Volley源码解析系列】初识Volley及其基本用法
- react-redux部分关键源码解析
- js解析与序列化json数据(一)json.stringify()的基本用法
- jQuery源码解析之构建jQuery之构建函数jQuery的7种用法
- 二.jQuery源码解析之构建jQuery之构建函数jQuery的7种用法
- Android Volley完全解析(一),初识Volley的基本用法
- Android Volley完全解析(一),初识Volley的基本用法
- Android Volley完全解析(一),初识Volley的基本用法
- Android Volley完全解析(一),初识Volley的基本用法