Redux 学习
1:action
action本质就是js对象。用来描述要执行的动作和参数。type就是要执行的动作。
{
type: ADD_TODO,
text: 'Build my first Redux app'
}
store.dispatch() 将 action 传到 store的唯一方法。
action创建函数
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
flux中
let BusApplicationActions = {
applicationSubmit:function(data){
AppDispatcher.dispatch({ //当调用 action 创建函数时,一般会触发一个 dispatch
actionType:BusApplicationConstant.APPLICATION_SUBMIT,
data:data,
})
},
}
redux中
需把 action 创建函数的结果传给 dispatch()
dispatch(addTodo(text))
store 里能直接通过 store.dispatch() 调用 dispatch() 方法,但是多数情况下你会使用 react-redux 提供的 connect() 帮助器来调用。
redux-actions
我们引用了一个redux-actions库,用来生成基本action type函数模板代码。它的handleAction可以简化reducers的写法,不用写那么多switch语句。
redux-actions:
[图片上传失败...(image-3afad0-1519784102770)]
[图片上传失败...(image-211543-1519784102770)]
原生的写法:
[图片上传失败...(image-54fbad-1519784102771)]
[站外图片上传中...(image-b72d62-1519784102771)]
2:state
store
store 就是把 action ,reducers 联系到一起的对象,Redux 应用只有一个单一的 store。
维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
通过 subscribe(listener) 注册监听器;
通过 subscribe(listener) 返回的函数注销监听器。
根据已有的 reducer 来创建 store 是非常容易的。在前一个章节中,我们使用 combineReducers()
将多个 reducer 合并成为一个。现在我们将其导入,并传递 createStore()
。
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
store.dispatch(addTodo('Learn about actions')) //原始redux发起action
reducer
接收旧的 state 和 action,返回新的 state,Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。
我们将以指定 state 的初始状态作为开始。Redux 首次执行时,state 为 undefined,此时我们可借机设置并返回应用的初始 state。
function todoApp(state = initialState, action) {
// 这里暂不处理任何 action,
// 仅返回传入的 state。
return state
}
怎么让每次发action的时候都能触发state跟新,就是每次发action触发reducer,store.dispatch方法会触发 Reducer 的自动执行。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入createStore方法
combineReducers()
所做的只是生成一个函数,这个函数来调用你的一系列 reducer,每个 reducer 根据它们的 key 来筛选出 state 中的一部分数据并处理,然后这个生成的函数再将所有 reducer 的结果合并成一个大的对象
state
必须将所有 state 都维护在 Redux 中吗? 可以用 React 的 setState() 方法吗?
没有 “标准”。有些用户选择将所有数据都在 Redux 中维护,那么在任何时刻,应用都是完全有序及可控的。也有人将类似于“下拉菜单是否打开”的非关键或者 UI 状态,在组件内部维护。适合自己的才是最好的。
使用局部组件状态是更好的。作为一名开发者,应该决定使用何种 state 来组装你的应用,每个 state 的生存范围是什么。在两者之间做好平衡,然后就去做吧。
这里有一些将怎样的数据放入 Redux 的经验法则:
应用的其他部分是否关心这个数据?
是否需要根据需要在原始数据的基础上创建衍生数据?
相同的数据是否被用作驱动多个组件?
能否将状态恢复到特定时间点(在时光旅行调试的时候)?
是否要缓存数据(比如:数据存在的情况下直接去使用它而不是重复去请求他)?组织state
react-reudx
react-reudx是基于 容器组件和展示组件相分离 的开发思想。
现在来创建一些容器组件把这些展示组件和 Redux 关联起来。技术上讲,容器组件就是使用 store.subscribe()
从 Redux state 树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件。你可以手工来开发容器组件,但建议使用 React Redux 库的 connect()
方法来生成,这个方法做了性能优化来避免很多不必要的重复渲染。(这样你就不必为了性能而手动实现 React 性能优化建议 中的 shouldComponentUpdate
方法。)
使用 connect()
前,需要先定义 mapStateToProps
这个函数来指定如何把当前 Redux store state 映射到展示组件的 props 中。例如,VisibleTodoList 需要计算传到 TodoList中的 todos,所以定义了根据 state.visibilityFilter来过滤 state.todos的方法,并在 mapStateToProps中使用。
除了读取 state,容器组件还能分发 action。类似的方式,可以定义 mapDispatchToProps()
方法接收 dispatch()
方法并返回期望注入到展示组件的 props 中的回调方法。例如,我们希望 VisibleTodoList向 TodoList组件中注入一个叫 onTodoClick的 props 中,还希望 onTodoClic能发 TOGGLE_TODO
这个 action:
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
最后,使用 connect() 创建 VisibleTodoList,并传入这两个函数。
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList