框架原理第 5 / 7 章
Redux Toolkit 与 connect
进入现代 Redux 工具链,并回看 connect 的实现思路。
Rtk redux toolkit
官方推荐的编写redux逻辑的标准方式
@reduxjs/toolkit,集成了redux-thunk等中间件
使用方式
创建store
//
import homeReducer from "./reducer";
import { configureStore } from '@reduxjs/toolkit'
export const store = configureStore({
reducer: {
home: homeReducer
}
})
export default store
创建分片reducer
❗ 提示
异步组件还可以从createAsyncThunk返回结果,使用extraReducer的方式来 实现dispatch的派发,但是代码会繁琐一些
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
const initState = {
count: 1
}
const countSlice = createSlice({
name: 'home',
initialState: initState,
reducers: {
//同步actions
addNumber(state, { payload }) {
state.count += payload
},
subNumber(state, { payload }) {
state.count -= payload
}
}
})
//异步action
export const fetchData = createAsyncThunk('fetchData', async (params, store) => {
const res = await new Promise(resolve => {
resolve({
data: {
count: 3
}
})
})
store.dispatch(addNumber(res.data.count))
})
//导出reducer
export default countSlice.reducer
//导出同步action
export const { addNumber, subNumber } = countSlice.actions
组件内使用
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addNumber, fetchData, subNumber } from '../store/reducer'
export class Home extends Component {
render() {
const { count, addCount, subCount, fetchCount } = this.props
return (
<div>
<div>Home</div>
<div> count: {count}</div>
<button onClick={e => addCount(1)}>+</button>
<button onClick={e => subCount(1)}>-</button>
<button onClick={e => fetchCount(1)}>fetchCount</button>
</div>
)
}
}
const mapStateToProps = (state) => ({ count: state.home.count })
const mapDispatchToProps = (dispatch) => ({
addCount: (num) => dispatch(addNumber(num)),
subCount: (num) => dispatch(subNumber(num)),
fetchCount: (num) => dispatch(fetchData(num))
})
export default connect(mapStateToProps, mapDispatchToProps)(Home)
数据不可变原理
底层使用了immerjs,实现创建一个新的对象,但是不变的部分,仍然引用原来不改变的属性,实现复用和,减少内存浪费
实现自定义的connect
connect本身是一个高阶函数,返回一个高阶组件
//connect.js
import React, { PureComponent } from 'react'
import { storeContext } from './provider'
// 一个高阶函数,返回一个高阶组件
export function connect(mapStateToProps, mapActionsToProps) {
return (WrapComponent) => {
class NewComponent extends PureComponent {
constructor(props, context) {
super(props)
this.state = mapStateToProps(context.getState())
}
componentDidMount() {
this.unSubsribe = this.context.subscribe(() => {
this.setState(mapStateToProps(this.context.getState()))
})
}
componentWillUnmount() {
this.unSubsribe()
}
render() {
const actions = mapActionsToProps(this.context.dispatch)
const state = mapStateToProps(this.context.getState())
return (
<WrapComponent {...this.props} {...state}{...actions} />
)
}
}
NewComponent.contextType = storeContext
return NewComponent
}
}
创建一个上下文用来共享整个store
import { createContext } from 'react'
export const storeContext = createContext()
export const Provider = storeContext.Provider