项目驱动是学习框架很是高效的一种方式。
学习 redux 全家桶推荐 react-douban:一个 React + Redux + React-Router 完整项目javascript
该笔记主要是下面三部分:前端
Redux是一个管理状态容器,将整个前端应用的状态都统一到一个地方管理。经过单一数据流操做,来实现单一状态。使得前端应用更加方便的管理状态。java
整个state就是一个object,能够将store理解为前端的数据库,没有setter,不能直接更改。
若是要更改state,则须要dispatch an action。而 action 则是一个对象,用于描述提交了什么操做,而不涉及对 state 具体的操做。
强制使用action来改变每一次的state,可让咱们更加容易追踪到每次state的变化。
而 Reducer 则是用来将 Action 和 State 串起来的一个函数。用于具体处理对 state 的改变。react
以上的过程差很少就是整个 Redux 的思想。git
在你的应用中state存储在一个 object tree,并且这个object tree 在该应用中是惟一一个的。
将全部state存在于应用中惟一一个object tree 带来的好处是:能够实现开发环境下的保存状态的历史状态,实现Undo/Redo等功能。github
改变 state 的惟一方式就是触发一个 action(action 是一个用于描述发生了什么的对象)数据库
为了描述action 如何具体改变 state tree,你须要编写reducers。Reducer 只是一些纯函数。
Reducer 接收 state 和 action 做为参数,并返回新的 state。json
Store就是保存数据的地方,能够看出是一个容器,整个应用就只能有一个store。Redux提供createStore()
函数来生成storeredux
import {createStore} from 'redux'
const store = createStore(app);复制代码
store 某个节点对应的数据集合就是state。能够经过store.getState()
得到。
Redux 规定,一个state对应一个View。State相同,则View相同。api
State 的变化会致使 View 的变化。可是用户接触不到State,只能接触到View。因此State的变化必须是View致使的。Action就是View发出的通知,表示State要发生改变了。
Action是一个对象,其中type属性是必须的,表示Action的名称。其余属性随意。
用于生成Action 的函数。
store.dispatch()
是View发出Actiion 的惟一办法。
import {createStore} from 'redux'
const store = createStore(fn);
store.dispatch(addTodo(text))复制代码
Store 收到Action以后,必须给出一个新的State,这样才能使View发生变化。这种State的计算过程叫作Reducer。
Reducer 是一个函数,它接受Action和当前的state做为参数,返回一个新的state。
整个应用的初始状态,能够做为state的默认值。
Reducer还能够进行拆分,而后经过combineReducers
方法,结合成一个大的Reducer。
首先用户发出Action。
store.dispatch(action)复制代码
而后store自动调用Reducer,而且传入两个参数:当前的state 和 收到的Action. Reducer 会返回新的state。
let nextState = reducer(previousState, action)复制代码
State一旦变化,Store就会调用监听函数。Listener能够经过store.getState()
获得当前状态。
Redux解决了同步状态更新的问题,可是异步操做却没有解决。
若是要 使Reducer在异步操做结束后自动执行,必须使用中间件。
createStore()
方法包含了参数applyMiddleware()
,
它是Redux的原生方法,做用是 将全部的中间件组成一个数组,依次执行
异步操做须要发出三种Action
因此流程也很清楚:
解决方案:
写出一个返回函数的 Action Creator,而后使用redux-thunk
中间件改造store.dispatch
。
import {createStore, applyMiddleware} from 'redux'
import thunk from 'react-thunk'
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)
export function fetchPost() {
}
export function requestPost(){}
export function receivePost(){}
export function handleError(err) {
}
export function requstAync() {
return function(dispatch){
// 请求发起时 dispatch action
dispatch(requestPost())
// 这里的fetchPost 是一个Promise
return fetchPost()
.then(response => response.json())
.then(json =>
// 请求成功时 dispatch action
dispatch(receivePost())
)
.catch(err =>
// 请求错误时 dispatch action
dispatch(handleError(err))
)
}
}复制代码
React-Redux将组件分为两种:
若是遇到一个组件既有UI和业务逻辑时,须要拆分红下面的结构:
外面是一个容器组件,里面包含若干个UI组件。容器组件负责与外部的通讯、传递数据给UI组件。
UI组件则负责页面显示。
用于从UI组件生成容器组件。能够这么来理解 connect 的做用。
connect 就是将 state 上的 props(属性)和 方法(dispatch)添加到对应的 UI组件上。
import {connect} from 'react-redux'
import {TodoList} from './TodoList'
export default connect()(TodoList)复制代码
上面的代码就将UI组件 TodoList 转换为一个容器组件。
每一个容器组件须要定义两方面的信息:
完整的connect
方法的API以下:
import {connect} from 'react-redux'
import {TodoList} from './TodoList'
function mapStateToProps(state){
return{
// do something
}
}
function mapDispatchToProps(dispatch){
return{
// do something
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)复制代码