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.propsconsole.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 } = actionswitch (type) {case 'add':return state + datacase 'minus':return state - datacase '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)}
}