前言
最近学react, 跟着react-redux的官方文档看了半天没看懂什么意思. 跟着视频过了一遍并且试着做了一个demo, 现在来整理以下
总览
我更喜欢使用我自己画的图来进行说明
接下来我用简单的比喻来帮助理解`
store
相当于万达广场state
相当于万达里面的商店, 比如小米之家, 魅族, 华为…reducer
相当于店长, 负责开店/进货/换货components
相当于消费者, 去store
内访问state
买东西
Reducers
reducer
相当于店长, 负责存储货物/进货/换货等服务, 我们看看reducer
的结构
interface XiaomiPhone {
id: number,
name: string
}
interface XiaomiStateActions {
type: string,
id: number,
name?: string
}
const defaultState: Array<XiaomiPhone> = [
{id: 0, name: "小米10"},
{id: 11, name: "小米10pro"},
];
export const xiaomiReducer = (state: Array<XiaomiPhone> = defaultState,
action: XiaomiStateActions) => {
switch (action.type) {
case "IMPORT":
return [...state, {id: action.id, name: action.name}];
case "SELL":
return state.filter(value => value.id !== action.id);
default:
return state
}
};
我们首先看xiaomiReducer
, 小米之家店长, 他有两个参数: state
和action
, state
便是这个商店的库存, 为XiaomiPhone(小米手机)的数组, defaultState
为创建这个商店时店长自带的库存, 这里自带小米10和小米10pro, action
为店长能提供的工作, 比如IMPORT
进货.
adReducer
店长, 他是放广告的, 他的reducer
长这样的:
export const adReducer = (state: string = "谁TM买小米啊?!",
action: adReducerAction) => {
switch (action.type) {
case "CHANGE_AD":
return action.ad;
}
};
如法炮制, 我们再做出meizuReducer
, huaweiReducer
, 最后我们把店长集合在一起, 变成Reducers
import {combineReducers} from "redux";
export const reducers = combineReducers({
ad: adReducer,
huawei: huaweiReducer,
meizu: meizuReducer,
xiaomi: xiaomiReducer
});
Store
我们把店长都集合在了一起, 但是店长没有店可不行, 于是把店长集合起来开个店吧
import {createStore} from "redux";
const store = createStore(reducers);
这样, 店长们就会按照combineReducers
定义的方法, huaweiReducer
开了一家huawei
, meizuReducer
开了一家meizu
…adReducer
放了个ad
此时, store里应该长这样:
>> store.getState()
{
ad: "谁TM买小米啊?!",
huawei: [
{id: 0, name: "华为p40", price: 3988}
],
xiaomi: [
{id: 0, name: "小米10"},
{id: 1, name: "小米10pro"},
],
meizu: [
{id: 0, name: "魅族16s Pro Max X Mate T"},
]
}
消费者即可用这种方法取得店铺里商品信息
Action & dispatch
dispatch
可以理解为store
里的大喇叭, action
则为大喇叭喊出来的命令
比如, 我是卖窝窝头的, 想在这里投放广告, 于是写下下面命令
const action = {type: "CHANGE_AD", ad: "窝窝头, 一块钱四个, 嘿嘿!"};
store.dispatch(action);
此时大喇叭便会发出CHANGE_AD
的命令, 所有的Reducer
店长都听见了, 但是只有adReducer
能够处理事件CHANGE_AD
, 于是他就跟着指令state = action.ad
更换了自己的state
库存, 此时store长这样
>> store.getState()
{
ad: "窝窝头, 一块钱四个, 嘿嘿!",
huawei: [
{id: 0, name: "华为p40", price: 3988}
],
xiaomi: [
{id: 0, name: "小米10"},
{id: 1, name: "小米10pro"},
],
meizu: [
{id: 0, name: "魅族16s Pro Max X Mate T"},
]
}
subscribe
我是一个米粉, 但是小米10pro老是缺货啊, 我想买小米10怎么办? 这时我发现, xiaomiReducer
要想进货, 必须发布IMPORT
喇叭才行, 于是我 订阅(subscribe) 了商店的喇叭, 如果喇叭一响就通知我一声, 看看小米10有没有货, 代码如下
store.subscribe(() => {
const state = store.getState();
if (state.xiaomi.length !== 0) {
/*买买买买买买买买买买买买*/
store.dispatch({type: "SELL", id: state.xiaomi[0].id})
/*买到手了*/
}
});
connect
假设我是一个小米手机零售商, 做中间商赚差价的事情, 但是我又没有自己的仓库, 我就是一个无状态的中间商, 此时我对于小米之家来说又是一个消费者
首先我们先创建我们的消费者中间商components
import React from "react";
const xiaomiMiddleman = ({xiaomiList, onSell}: XiaomiMiddlemanInterface) => (
<ul>
{
xiaomiList.map((value, index) => (
<li key={index} onClick={() => onSell(value.id)}>{value.name}</li>
))
}
</ul>
);
xiaomiMiddleman
便是无状态的组件, 他没有仓库state
.
有两个参数
xiaomiList
为商品列表, 从store获取onSell
为从中间商时购买的回调, 用于通知store
我们便可以使用subscribe
和dispatch
进行绑定了, 但是是不是有点麻烦?
新办法: 我们直接把中间商和小米之家连起来就行了!
const stateConnectProps = (state: { xiaomi: Array<XiaomiPhone> }) => (
{xiaomiList: state.xiaomi}
);
const dispatchConnectProps = (dispatch: Function) => (
{onSell: (id: number) => {dispatch({type: "SELL", id})}}
);
export default connect(stateConnectProps, dispatchConnectProps)(xiaomiMiddleman);
看看这两个函数,
stateConnectProps
: 把state
和props
连起来, 返回的xiaomiList: state.xiaomi
意思就是把getState().xiaomi
连接到参数xiaomiList
上dispatchConnectProps
: 把dispatch
和props
连起来, 这时调用onSell就相当于调用(id: number) => {dispatch({type: "SELL", id})}
, dispatch将由connecct给出
最后总体:
import React from "react";
const xiaomiMiddleman = ({xiaomiList, onSell}: XiaomiMiddlemanInterface) => (
<ul>
{
xiaomiList.map((value, index) => (
<li key={index} onClick={() => onSell(value.id)}>{value.name}</li>
))
}
</ul>
);
const stateConnectProps = (state: { xiaomi: Array<XiaomiPhone> }) => (
{xiaomiList: state.xiaomi}
);
const dispatchConnectProps = (dispatch: Function) => (
{onSell: (id: number) => {dispatch({type: "SELL", id})}}
);
export default connect(stateConnectProps, dispatchConnectProps)(xiaomiMiddleman);
结尾
此文章是为那些看不懂官方文档的概念而写的, 没有描述具体细节, 希望对大家理解概念有所帮助