react-redux是react插件
将所有组件分成两大类:UI组件和容器组件
安装npm install react-redux -S
UI组件:
- 只负责UI的呈现,不带有任何业务逻辑
- 不使用this.state
- 所有数据都由this.props提供
- 不使用任何Redux的API,不需要使用store
容器组件:
- 负责管理数据和业务逻辑,不负责UI的呈现
- 带有内部状态
- 使用Redux的API
组件结构
- 用容器组件包裹UI组件
- 容器组件负责与外部的通信,将数据传给UI组件
- UI组件渲染出视图
- connect函数(来自react-redux插件):连接React组件与React store
关键字
- connect
- Provider
App修改为UI组件
- index.js
import ReactDOM from 'react-dom'
import App from './App'
import { createStore } from 'redux'
import { counter } from './redux/reducers'
import { Provider } from 'react-redux'
const store = createStore(counter)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
- App.jsx
import React, { Component, createRef } from 'react'
import { connect } from 'react-redux'
import * as actions from './redux/action'
class App extends Component {
constructor(props) {
super(props)
this.selectRef = createRef()
}
compute = (method) => {
const selectDom = this.selectRef.current,
selectVal = Number(selectDom.value);
// 使用传入的props.actions
this.props[method](selectVal)
}
render() {
// 将App改造为UI组件
const { count } = this.props
console.log('【app】', this)
return (
<>
<h1>数值:{count}</h1>
<select ref={this.selectRef}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={() => this.compute('add')}>+</button>
<button onClick={() => this.compute('minus')}>-</button>
<button onClick={() => this.compute('add_odd')}>奇数加</button>
<button onClick={() => this.compute('add_delay')}>延迟加</button>
</>
)
}
}
// 用connect函数处理App再暴露出去
export default connect(
state => ({
count: state // 这里的state是从redux容器中获取到的数据
}),
{ ...actions }
// 要解构出来!否则props里拿不到
// 这样即可在App这个UI组件里通过this.props.actions来使用
)(App)
connect方法接收2个参数
- 函数
mapStateToProps
,建立state对象到props对象的映射关系
(redux store里的state可以通过UI组件的props获取)mapDispatchToProps
,建立一个store.dispatch方法到props对象的方法
(redux里面action creators创建的函数可以通过props获取)
使用中间件
reducer:纯函数,只承担计算state的功能
view:与state意义对应
action:存放数据的对象,只能被别人操作?
同步:action发出后,reducer立即计算出state
异步:action发出后,过段时间再执行reducer
中间件:一个函数,对store.dispatch方法进行改造,在发出action和执行reducer两步之间添加了其他功能
- index.js(引入中间件)
import ReactDOM from 'react-dom'
import App from './App'
// 引入中间件
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { counter } from './redux/reducers'
import { Provider } from 'react-redux'
const store = createStore(counter, applyMiddleware(thunk))
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
- reducer.js(只有同步方法)
export function counter(state = 0, action) {
const { type, data } = action
switch (type) {
case 'add':
return state + data
case 'minus':
return state - data
case 'add_odd':
if (data % 2 !== 0) {
return state + data
}
// 这里面没有异步方法
default:
return state
}
}
- action.js (增加异步方法)
export function add(param) {
return {
type: 'add', // 方法名
data: param // 对应参数
}
}
export function minus(param) {
return {
type: 'minus',
data: param
}
}
export function add_odd(param) {
return {
type: 'add_odd',
data: param
}
}
// 改造成异步action
export function add_delay(param) {
return dispatch => {
setTimeout(() => {
dispatch(add(param))
}, 1000)
}
}