基础使用
const { legacy_createStore } = require('redux')
const createStore = legacy_createStore
const initialState = {
count: 0
}
// reducer 必须是一个纯函数
const reducer = function (state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, ...{ count: state.count + 1 } }
break;
case 'ADD_NUMBER':
return { ...state, ...{ count: state.count + action.num } }
break;
default:
return state
break;
}
}
// 创建store
const store = createStore(reducer)
// 订阅store的修改
store.subscribe(() => {
console.log(store.getState())
})
const action = { type: 'INCREMENT' }
const action1 = { type: 'ADD_NUMBER', num: 9 }
// 派发action
store.dispatch(action)
store.dispatch(action1)
自定义connect函数(返回一个高阶组件)
import { PureComponent } from "react"
import store from '../store';
export function connect(mapStateToProps, mapDispatchToProps) {
// 返回一个高阶组件
return function enhanceHOC(WrapperComponent) {
return class extends PureComponent {
constructor(props) {
super(props)
this.state = {
storeState: mapStateToProps(store.getState())
}
}
componentDidMount() {
// 订阅state改变
this.unsubscribe = store.subscribe(() => {
this.setState({
storeState: mapStateToProps(store.getState())
})
})
}
componentWillUnmount() {
// 取消订阅
this.unsubscribe()
}
render() {
return (
<WrapperComponent
{...this.props}
{...mapStateToProps(store.getState())}
{...mapDispatchToProps(store.dispatch)}
/>
)
}
}
}
}
使用
class App extends Component {
render() {
const { count, addNum } = this.props
return (
<div>
<span>count: { count }</span>
<button onClick={() => addNum(8)}>+8</button>
</div>
);
}
}
const mapStateToProps = (state) => ({
count: state.count
})
const mapDispatchToProps = (dispatch) => ({
addNum: (num) => {
dispatch(addAction(num))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(App)
context
上面封装的connect函数还有对store的依赖,这其实是不应该的,因为我们想要把connect作为一个库文件进行发布,所以我们应该想办法取消这个依赖
做法是使用context
// context.js
import { createContext } from "react";
export const StoreContext = createContext()
// connect.js store换成context的值,我们应该让使用者给我们传入
import React, { PureComponent } from "react"
import { StoreContext } from './context'
export function connect(mapStateToProps, mapDispatchToProps) {
// 返回一个高阶组件
return function enhanceHOC(WrapperComponent) {
class EnhanceComponent extends PureComponent {
constructor(props, context) {
super(props)
this.state = {
// 此处不能直接this.context 因为还没有这个值,可以用constructor第二个参数
storeState: mapStateToProps(context.getState())
}
}
componentDidMount() {
// 订阅state改变
this.unsubscribe = this.context.subscribe(() => {
this.setState({
storeState: mapStateToProps(this.context.getState())
})
})
}
componentWillUnmount() {
// 取消订阅
this.unsubscribe()
}
render() {
return (
<WrapperComponent
{...this.props}
{...mapStateToProps(this.context.getState())}
{...mapDispatchToProps(this.context.dispatch)}
/>
)
}
}
EnhanceComponent.contextType = StoreContext
return EnhanceComponent
}
}
// 用户传入 项目入口文件 index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './app.jsx';
import { StoreContext } from './utils/context';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
{/* 此处传入store */}
<StoreContext.Provider value={store}>
<App />
</StoreContext.Provider>
);