一.基本概念
redux有三个基本的概念:action reducer store
1.action:
是把数据传到store的有效载荷,它是store数据的唯一来源,用法是通过store.dispatch()方法将action传到store
2.reducer:
action描述了一些事件发生的事实,但是并没有明确指出state如何变化的,所以reducer用来指出如何更新,reducer是一个纯函数
不要在reducer里面做这些操作
- 修改传入参数;
- 执行有副作用的操作,如 API 请求和路由跳转;
- 调用非纯函数,如 Date.now() 或 Math.random()
总之action就像是领导,告诉reducer该干什么活,reducer再对store进行处理更新
3.store: 一个应用只有一个store
store有如下几个职责
- 维持应用的state
- 提供getState()方法获取state
- 提供dispatch方法更新state
- 通过 subscribe(listener) 注册监听器
总之store提供了一些方法将action和reducer联系在一起
二.详细介绍
1.action:action是一个普通的对象,redux规定action里面的type字符串类型字段用来代表执行的动作,还可以存放一些其他的想要操作的字段
{
type: 'ADD_TODO',
text:'',
}
但是实际上我们需要一个函数来为我们创建Action,例如一个addTodo函数
const addTodo = text => ({
type: 'ADD_TODO',
text,
})
2.reducer:reducer是一个纯函数
当它被Redux调用的时候会为他传递两个参数state和action,reducer会根据action的type来对旧的state进行更新,返回新的state
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
id: action.id,
text: action.text,
str: action.str,
completed: false
}
]
case 'TOGGLE_TODO':
return state.map(todo =>
(todo.id === action.id)
? {...todo, completed: !todo.completed}
: todo
)
default:
return state
}
}
注意reducer函数里面的几点:
- 不要修改state
- 在 default 情况下返回旧的 state
- 如果没有旧的State,就返回一个initialState
如果在default或没有传入旧State的情况下不返回旧的State或initialState。。。那么当前的State会被重置为undefined!!
真正开发项目的时候State会涉及很多功能,在一个Reducer处理所有逻辑会非常混乱,,所以需要拆分成多个小Reducer,每个Reducer只处理它管理的那部分State数据。然后在由一个主rootReducers来专门管理这些小Reducer。
3.store
createStore有两个参数Reducer 和 initialState
let store = createStore(rootReducers, initialState);
store有四个方法。
getState: 获取应用当前State。
subscribe:添加一个变化监听器。
dispatch:分发 action。修改State。
replaceReducer:替换 store 当前用来处理 state 的 reducer。
常用的是dispatch,它是修改state的唯一途径
// action
const addTodo = text = ({
type: 'ADD_TODO',
text,
})
store.dispatch(addTodo('textval'))
二.react-redux
redux是独立的,它与react没有任何关系,React-Redux是官方提供的一个库,用来结合redux和react的模块。
根据官方的todolist,补充一下react组件类型的知识点
React redux设计思想是根据容器组件和展示组件分离的思想开发
通俗的说,如果你需要state和生命周期,那么你就要用class容器组件
React-Redux提供了两个接口Provider、connect。
Provider
provider是react的一个组件,它的作用是保存store给子组件的connect使用,Provider来 魔法般的让所有容器组件都可以访问 store,而不必显示地传递它。只需要在渲染根组件时使用即可,它的唯一功能就是传入store对象
1.通过getChildContext方法把store保存到context里。
2.后面connect中会通过context读取store。
它看起来是这个样子
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp)
render(
<Provider store={store}>
<App />
</Provider>
document.getElementById('root')
一部分核心源码
getChildContext() {
return { store: this.store }
}
constructor(props, context) {
super(props, context)
this.store = props.store
}
connect
connect会将state,dispatch转换成props传递给子组件,一般此代码写在container容器组件里面,里面的参数传其中的几个都可以
import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
case 'SHOW_ALL':
default:
return todos
}
}
const mapStateToProps = state => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
const mapDispatchToProps = dispatch => ({
toggleTodo: id => dispatch(toggleTodo(id))
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
这个方法会使用黑魔法把state,dispatch转换成props传递给react组件
mapStateToProps:
mapStateToProps是一个普通函数,当它被connect 调用的时候,会为它传递一个参数state,它主要的事情就是 返回需要传递给子组件的state,然后connect会拿到返回数据写到组件中,然后组件就可以通过props读取数据了~
const mapStateToProps = state => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
mapDispatchToProps:
与mapStateToProps很像,也是一个函数,他被connect调用的时候会被传递一个dispatch 参数,它负责返回一个dispatchProps
const mapDispatchToProps = dispatch => ({
toggleTodo: id => dispatch(toggleTodo(id))
})
connect收到数据之后,会把它放在react组件上,然后子组件就可以通过props拿到 toggleTodo去使用,每当调用这个方法就会更新state
this.props.toggleTodo('hello');
网友评论