React-redux 通俗入门理解 我在万达卖窝窝头

none

咕鸽框架 更新2020年05月22日 142 5615字 CID:P12

前言

最近学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, 小米之家店长, 他有两个参数: stateaction, 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
    我们便可以使用subscribedispatch进行绑定了, 但是是不是有点麻烦?

新办法: 我们直接把中间商和小米之家连起来就行了!

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 : 把stateprops连起来, 返回的xiaomiList: state.xiaomi意思就是把getState().xiaomi连接到参数xiaomiList
  • dispatchConnectProps : 把dispatchprops连起来, 这时调用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);

结尾

此文章是为那些看不懂官方文档的概念而写的, 没有描述具体细节, 希望对大家理解概念有所帮助

版权声明:
本文基于《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
文章链接:http://blog.z31.xyz/index.php/archives/12/ (转载时请注明本文出处及文章链接)

评论