redux原理解读
在控制台中打印redux
const redux = require('redux')
// console.log(redux) // createStore 创建仓库 + applyMiddleware 使用中间件 + combineReducers 分模块使用redux
console.log(redux.createStore(() => {})) // 至少传入一个函数 -- reducer --- 纯函数
// dispatch: 触发修改状态的方式
// subscribe: 订阅 -- 数据改变,要以何种方式 更新视图
// getState: 获取状态
一.单纯使用redux
1.引入redux
import { createStore } from 'redux'
/**
* 如果需要获取状态 store.getState()
* 如果需要订阅 更新视图 store.subscribe(fn) fn是关键 (状态/属性的改变会引起视图的二次渲染 --- 入口文件)
* 如果需要触发更改状体啊 store.dispatch({ type: '' })
*/
2.创建redcer – 数据的改变必须经过纯函数修改
const defaultState = {
count: 0
}
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 }
case 'DECREMENT':
return Object.assign({}, state, { count: state.count - 1 })
default:
return state
}
}
export default reducer
3.创建store
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
4.入口文件处 订阅变化
import React from 'react'
import ReactDOM from 'react-dom'
import App from './redux/App'
import store from './redux/store'
function render () {
ReactDOM.render(
<App />,
document.getElementById('root')
)
}
render()
// 如果状态一旦发生改变,就重新执行 render 函数(自定义函数)
store.subscribe(render)
5.组件处使用状态管理器
import React, { Component } from 'react'
import store from './store'
export default class App extends Component {
render() {
return (
<div>
<button onClick = { () => {
// 修改状态
store.dispatch({ type: 'DECREMENT'})
}}>-</button>
{ store.getState().count }
<button onClick = { () => {
store.dispatch({ type: 'INCREMENT'})
}}>+</button>
</div>
)
}
}
二.redux + react-redux
react-redux ---- 容器组件 + 展示组件(UI组件)
以todolist为例
1.入口文件
import React from 'react'
import ReactDOM from 'react-dom'
import App from './todolist/TodoList'
import { Provider } from 'react-redux' // 顶级组件中使用
import store from './todolist/store'
ReactDOM.render(
<Provider store = { store }>
<App />
</Provider>,
document.getElementById('root')
)
2.创建reducer
const defaultState = {
list: ['task 1', 'task 2', 'task 3']
}
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'ADD_ITEM':
// 对象合并,合并list(数组)
return { ...state, list: [ ...state.list, action.data ]}
case 'REMOVE_ITEM':
const arr = state.list.filter((item, index) => {
return index !== action.index
})
return { ...state, list: arr }
default:
return state
}
}
export default reducer
3.创建store
import { createStore } from 'redux'
import reducer from './reducer'
export default createStore(reducer)
- 表单添加数据
import React, { Component } from 'react'
import { connect } from 'react-redux'
class Form extends Component {
state = {
keyword: ''
}
handlerChange = (e) => {
this.setState({ keyword: e.target.value })
}
handlerKeyUp = (e) => {
if (e.keyCode === 13) {
this.props.addItem(this.state.keyword)
}
}
render() {
return (
<input
type="text"
value = { this.state.keyword }
onChange = { this.handlerChange }
onKeyUp = { this.handlerKeyUp }
/>
)
}
}
const mapDispatchToProps = dispatch => { // dispatch 是该函数的默认参数
return {
addItem (data) { // 可以在组件中通过 this.props.addItem(params)调用
dispatch({
type: 'ADD_ITEM',
data
})
}
}
}
// 如果不需要获取状态,第一个参数写为null
export default connect(null, mapDispatchToProps)(Form)
5.遍历数据以及删除数据
import React, { Component } from 'react'
import { connect } from 'react-redux'
class List extends Component {
removeData = (index) => {
return () => {
this.props.removeItem(index)
}
}
// removeData = () => {
// }
render() {
return (
<ul>
{
this.props.list.map((item, index) => (
<li key = { index }>
{ item }
<button onClick = { this.removeData(index) }>删除</button>
{/* <button onClick = { () => {
this.removeData(index)
} }>删除</button> */}
</li>
))
}
</ul>
)
}
}
const mapStateToProps = state => { // state 就是全局的状态管理器
return {
list: state.list // 组件中通过 this.props.list 获取到想要的数据
}
}
const mapDispatchToProps = dispatch => {
return {
removeItem (index) {
dispatch({
type: 'REMOVE_ITEM',
index
})
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(List)
7.为什一开始可以拿到初始化数据
观测 redux 源码,得知,自动调用一次dispatch
// When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
dispatch({ type: ActionTypes.INIT })